2

I want to get the day of the week from a date in Java. Why would this return Friday when it is, in fact, Tuesday?

new java.text.SimpleDateFormat("EEEE").format(new java.util.Date(2015, 6, 9))

PS I know java.util.Date(int year, int month, int day) is deprecated, maybe that has something to do with it.

bmscomp
  • 777
  • 1
  • 11
  • 21
Brian T Hannan
  • 3,925
  • 18
  • 56
  • 96
  • 2
    I guess I'm fascinated about why your first inclination upon having this problem was to post on stackoverflow instead of, you know, going to the java.util.Date javadocs and reading the constructor documentation. Everything you need to know is right there. – scottb Jun 09 '15 at 14:49
  • Related: [Date from EditText](https://stackoverflow.com/questions/17674308/date-from-edittext). – Ole V.V. May 04 '21 at 12:37

2 Answers2

7

The month argument in that deprecated constructor starts at 0 for January, so you probably wanted new Date(115, 5, 9) if you're talking about June 9th (the 115 is because the year argument is "since 1900").

From the documentation:

Parameters:

year - the year minus 1900.

month - the month between 0-11.

date - the day of the month between 1-31.

(My emphasis.)

You've said you want to do this as a one-liner. In Java 8, you could do:

String day = LocalDate.of(2015, 6, 9).format(DateTimeFormatter.ofPattern("EEEE"));

that uses java.time.LocalDate and java.time.format.DateTimeFormatter.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Wow! Why would they do that LOL?? – Brian T Hannan Jun 09 '15 at 14:41
  • 3
    @BrianTHannan class `java.util.Date` was unfortunately badly designed. – Jesper Jun 09 '15 at 14:42
  • @BrianTHannan: It's a fairly common convention for month numbers. Amongst other things, it lets you have a lookup array for month names without having to either waste the first entry or always remember to subtract one. – T.J. Crowder Jun 09 '15 at 14:42
  • 1
    Javascript has this same problem where the Month is 0 indexed and everything else is not. This is the story about how one of my projects deployed a month late. – KevinL Jun 09 '15 at 14:43
  • I also see that the year param is the year minus 1900 so do I want 115 instead of 2015 as well? – Brian T Hannan Jun 09 '15 at 14:43
  • 3
    @BrianTHannan If you're using Java 8, forget about `java.util.Date` and use the new API in package `java.time` instead. Otherwise, use `java.util.Calendar` instead of the deprecated constructor. – Jesper Jun 09 '15 at 14:45
  • 2
    Try to avoid using `java.util.Date` if you possibly can. – Louis Wasserman Jun 09 '15 at 14:45
  • I'm trying to the above call in one line. How could I do that using Calendar in one line? – Brian T Hannan Jun 09 '15 at 14:45
  • 1
    There is usually a reason why stuff is deprecated. And 0 based months and 1 based days is an excellent reason to deprecate this class. – Peanut Jun 09 '15 at 14:46
  • 1
    @BrianTHannan: Wow, I haven't used `java.util.Date` in so long I'd forgotten about the year aspect. Yes, **if** you use this constructor, which has been deprecated for something like **15 years**, you'd want 115 instead of 2015. But again, seriously, look at using an alternative. – T.J. Crowder Jun 09 '15 at 14:48
  • 2
    @Peanut I'd say the fact that it's year minus 1900 is an even worse design mistake for a class designed in the 1990s (two digit year?? everybody knew about the Y2K problem then!). – Jesper Jun 09 '15 at 14:49
  • @Jesper: Not a two-digit year, just year - 1900. You can use 115 for 2015. But of course, one shouldn't. – T.J. Crowder Jun 09 '15 at 14:50
  • @T.J.Crowder Yes but year - 1900 is clearly intended for people to pass a two-digit year, even though it works with values > 99. – Jesper Jun 09 '15 at 14:51
  • @BrianTHannan: *"I'm trying to the above call in one line"* With just `Calendar` I don't believe you can, you'll have to write yourself a static function and then call it. – T.J. Crowder Jun 09 '15 at 14:51
  • 1
    @Jesper: I wouldn't say that at all. – T.J. Crowder Jun 09 '15 at 14:51
  • @T.J.Crowder I would have expected the designer of that constructor to understand that referring to years as "100", "101", "102", ... is totally unintuitive for someone in the 21st century (whereas '96, '97, '98, was normal in the 20th century). – Jesper Jun 09 '15 at 14:55
  • 2
    @BrianTHannan: But if you follow Jesper's advice (and he's not usually going to steer you wrong) and use `java.time`, I think the one-liner I just added to the answer does it. – T.J. Crowder Jun 09 '15 at 14:58
  • @Jesper: A *lot* of programming is unintuitive. :-) I can't for the life of me figure what their rationale for using "since 1900" was, though. I get the month thing. But the year thing is just...even dumber than the rest of the class, which I think you'll agree is saying something. :-) – T.J. Crowder Jun 09 '15 at 15:04
1

java.time

The legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

Solution using modern date-time API:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        System.out.println(DateTimeFormatter.ofPattern("EEEE", Locale.ENGLISH).format(LocalDate.of(2015, 6, 9)));

        // Alternatively
        System.out.println(LocalDate.of(2015, 6, 9).getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
    }
}

Output:

Tuesday
Tuesday

Learn more about the the modern date-time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110