1

I want to do this simple thing in Java. The correct answer is supposed to be 'WEDNESDAY'. What is wrong with this? I took the example from the documentation for the Calendar class.

import java.util.*;
import java.lang.Integer;

class Dumb {
  public static List<String> dows = Collections.unmodifiableList(Arrays.asList("SUNDAY","MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY"));

  public static String getDay(String day, String month, String year) {
   // get the supported ids for GMT-08:00 (Pacific Standard Time)
   String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
   // if no ids were returned, something is wrong. get out.
   if (ids.length == 0)
       System.exit(0);
   // create a Pacific Standard Time time zone
   SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
   // set up rules for Daylight Saving Time
   pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
   pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);

   // create a GregorianCalendar with the Pacific Daylight time zone
   // and the desired date and time
   Calendar calendar = new GregorianCalendar(pdt);
   calendar.set(Calendar.MONTH, Integer.valueOf(month));
   calendar.set(Calendar.DAY_OF_MONTH, Integer.valueOf(day));
   calendar.set(Calendar.YEAR, Integer.valueOf(year)); 

   // print out a bunch of interesting things
   System.out.println("SUNDAY: " + calendar.SUNDAY);
   System.out.println("MONDAY: " + calendar.MONDAY);
   System.out.println("TUESDAY: " + calendar.TUESDAY);
   System.out.println("WEDNESDAY: " + calendar.WEDNESDAY);
   System.out.println("THURSDAY: " + calendar.THURSDAY);
   System.out.println("FRIDAY: " + calendar.FRIDAY);
   System.out.println("SATURDAY: " + calendar.SATURDAY);
   System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
   System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
   System.out.println("DATE: " + calendar.get(Calendar.DATE));
   System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
  int dow = calendar.get(Calendar.DAY_OF_WEEK);
  return dows.get(dow-1);
    }
}

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    String month = in.next();
    String day = in.next();
    String year = in.next();

    System.out.println(getDay(day, month, year));
}

}

This code produces the following output:

SUNDAY: 1 
MONDAY: 2
TUESDAY: 3
WEDNESDAY: 4
THURSDAY: 5
FRIDAY: 6
SATURDAY: 7
YEAR: 2015
MONTH: 8
DATE: 5
DAY_OF_WEEK: 7
SATURDAY
slashdottir
  • 7,835
  • 7
  • 55
  • 71
  • 1
    FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jul 22 '18 at 19:40

5 Answers5

4

tl;dr

get day of week as a string for a particular date

  • You are working too hard.
  • You are using the wrong classes.

We can reduce your code to a one-liner:

LocalDate.of(                    // A date-only value, without time-of-day, without time zone.
    Integer.valueOf( "2018" ) ,  // Sane numbering. Ex: number `2018` is year 2018.
    Integer.valueOf( "1" ) ,     // Sane numbering. Months 1-12 are January-December.
    Integer.valueOf( "23" ) 
)                                // Returns a `LocalDate` object.
.getDayOfWeek()                  // Returns a `DayOfWeek` enum object.
.getDisplayName(                 // Calls a method on the enum object to automatically localize the name of the day-of-week.
    TextStyle.FULL ,             // Specify how long or abbreviated.
    Locale.US                    // Locale determines the human language and cultural norms used in localization.
)

See this code run live at IdeOne.com.

Tuesday

I suggest searching Stack Overflow before struggling with such code. This topic has been asked and answered many times already.

java.time

You are using terribly troublesome classes that were supplanted years ago by the java.time classes. Never again touch those legacy classes.

Parse your input strings as a date-only value, without time-of-day, without time zone. That would be a LocalDate object.

LocalDate ld = LocalDate.of(
    Integer.valueOf( y ) ,    // Sane numbering. Ex: number `2018` is year 2018.
    Integer.valueOf( m ) ,    // Sane numbering. Months 1-12 are January-December.
    Integer.valueOf( d ) 
) ;

Get the day-of-week using the handy DayOfWeek enum. This class pre-defines seven objects, one for each day of the week. You will find some handy methods on that class as well, such as the localization feature used below.

Java has an extraordinarily powerful and flexible enum facility. If unfamiliar, study the Oracle Tutorial.

DayOfWeek dow = ld.getDayOfWeek() ; 

Generate a String with the name of the day of the week. No need to hard-code English. Let java.time automatically localize for you.

To localize, specify:

  • TextStyle to determine how long or abbreviated should the string be.
  • Locale to determine:
    • The human language for translation of name of day, name of month, and such.
    • The cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.

Example:

Locale l = Locale.CANADA_FRENCH ;  // Or, Locale.UK, Locale.US, etc.
String output = dow.getDisplayName( TextStyle.FULL , l ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

Because the month is zero based.

I should have subtracted 1 from the month.

argh

slashdottir
  • 7,835
  • 7
  • 55
  • 71
  • You cannot condemn an entire platform for one badly written library. Indeed, the entire information technology has for decades ignored the vital topic of date-time handling. The first serious attempt at a robust sophisticated date-time library was [*Joda-Time*](http://www.joda.org/joda-time/), which happens to be written in Java, mainly by Stephen Colebourne. He went on to learn from that experience to make the industry-leading date-time framework, [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html). You’ll find *java.time* bundled with… Java. – Basil Bourque Jul 22 '18 at 19:44
1

Get a look at LocalDate and Try this:

Scanner in = new Scanner(System.in);
String month = in.next();
String day = in.next();
String year = in.next();
LocalDate ld = LocalDate.of(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(day));
System.out.println(ld.getDayOfWeek());

There are nice classes in java.time package.

RubenDG
  • 1,365
  • 1
  • 13
  • 18
0

Java date time issue fixed in java8 DateTime. use below code. your problem will be fixed.

public static String getDay(String day, String month, String year) {
    return LocalDate.parse(day+"-"+month+"-"+year , DateTimeFormatter.ofPattern( "dd-MM-yyyy" ))
            .getDayOfWeek()
            .getDisplayName(TextStyle.FULL_STANDALONE , Locale.ENGLISH);
}
GolamMazid Sajib
  • 8,698
  • 6
  • 21
  • 39
0

Edit: Based on the latest comment from Ole V.V. There is no error in the program. Just re-tried it in my workstation and it is due to the month numbering scheme is 0-based instead of 1 as highlighted by slashdottir.

I think there is probably a logical error in the program.

// create a GregorianCalendar with the Pacific Daylight time zone
// and the desired date and time
   Calendar calendar = new GregorianCalendar(pdt);
   calendar.set(Calendar.MONTH, Integer.valueOf(month));
   calendar.set(Calendar.DAY_OF_MONTH, Integer.valueOf(day));
   calendar.set(Calendar.YEAR, Integer.valueOf(year));

In this portion of the code, the DAY_OF_WEEK or DAY_OF_WEEK_IN_MONTH is not set but...

towards the end of the method, we are trying to retrieve it anyway:

 System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
 int dow = calendar.get(Calendar.DAY_OF_WEEK);
 return dows.get(dow-1);

So, you are essentially getting the default value of DAY_OF_WEEK which is 7 (reference) - also the value of dow variable, therefore dow - 1 will always be 6 and dows.get(6) will always return SATURDAY.

Trying to set DAY_OF_WEEK_IN_MONTH with Calendar class may turn out to be tricky. It would be best to use the features in java.time package as suggested by Ruben DG and sajib.

Lalit
  • 1,944
  • 12
  • 20
  • @BasilBourque - Agreed. I just attempted to reproduce the error in my workstation and responded with what I observed and alongside highlighted the responses by our fellow community members. :) – Lalit Jul 22 '18 at 19:52
  • Very well. I retract my comment. I suggest adding a mention of these classes being legacy now. – Basil Bourque Jul 22 '18 at 20:02
  • Thanks for the suggestion. :) From next time, I'll make it a point to include such points. In this instance however, I don't think there will be a need for me to add anything as your response is pretty comprehensive and provides the solution (along with the background details). :) – Lalit Jul 22 '18 at 20:18
  • 1
    Flawed answer. `Calendar` will compute `DAY_OF_WEEK` (and `DAY_OF_WEEK_IN_MONTH`) from month, day of month and year. I agree that using `Calendar` may be tricky, though, and that it’s better to use java.time. – Ole V.V. Jul 23 '18 at 14:14
  • @OleV.V. - Thanks for pointing this out. When I looked at the documentation, I just assumed that it was an attribute that we'll need to set explicitly but not really. I've edited my answer based on your response. :) – Lalit Jul 23 '18 at 14:49