1

I have written the following Java code to get a the first day of a week of year.

    Calendar cal = Calendar.getInstance(Locale.GERMAN);
    cal.clear();
    cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.MONDAY);
    cal.set(Calendar.YEAR, 2016);
    cal.set(Calendar.WEEK_OF_YEAR, weekNumber);

    DateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");

    System.out.println( sdf.format(cal.getTime()) );

By using the input week of year 53 it should result into an error acutally because this week of year does not exist in 2016. Instead it shows me the next possible first date from next year.

Is there a neat way to correct my code or do I have to check the input week of year by myself?

Thanks for your help.

Gaku87
  • 11
  • 2
  • Does this help? http://stackoverflow.com/q/10893443/535275 – Scott Hunter Dec 25 '16 at 12:55
  • If you already have a `GregorianCalendar` object (which is the default for `Calendar.getInstance()` ) for some time in the year, calling `getWeeksInWeekYear()` on it will tell you how many week of year values this year has. – Powerlord Dec 25 '16 at 13:52
  • Thank you. The first post solved my problem. Indeed it was already asked however I could not find the question. – Gaku87 Dec 25 '16 at 19:45
  • FYI, the 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 Apr 10 '18 at 04:03
  • Re-opened this Question, as the supposed duplicate had *nothing* to do with week-of-year. – Basil Bourque Apr 10 '18 at 04:28

1 Answers1

0

tl;dr

If you mean a standard ISO 8601 week, use the YearWeek class from the ThreeTen-Extra library.

For specific week number in specific week-based year:

YearWeek.of(                         // Standard ISO 8601 week, where week # 1 has the first Thursday of the calendar year, and runs Monday-Sunday.
    2018 ,                           // Week-based year, NOT calendar year.
    37                               // Week-of-week-based-year. Runs 1-52 or 1-53. 
)
.atDay( DayOfWeek.MONDAY )           // Returns a `LocalDate` object.

➡ Trap for java.time.DateTimeException if the input is not valid, if there is no such week in that week-based-year.

For current week:

YearWeek.now(                        // Standard ISO 8601 week, where week # 1 has the first Thursday of the calendar year, and runs Monday-Sunday.
    ZoneId.of( "Pacific/Auckland" )  // Determining a week means determining a date, and that requires a time zone. For any given moment, the date varies around the globe by zone.
)
.atDay( DayOfWeek.MONDAY )           // Returns a `LocalDate` object.

Define “week”

Define what you mean by “week”. Is week # 1 the one with January 1st? Is week # 1 the first to have all seven days composed of days in the new year? If so, what is the first-last days of the week, Sunday-Saturday or Monday-Sunday or something else? Or is week # 1 the first to have a certain day of the week?

The troublesome old date-time classes defined a week by depending on Locale. If you fail to specify a Locale, the JVM’s current default Locale is silently implicitly applied. So your results can vary at runtime.

If possible I recommend using the standard ISO 8601 week definition. The week runs from Monday-Sunday, and week # 1 contains the first Thursday of the calendar year. So there are either 52 or 53 weeks per year.

Getting the current week means getting the current date. A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

If you simply want a certain day-of-week on or before that date, then never mind about the week. Use a TemporalAdjuster implementation found in TemporalAjdusters. Specify your day-of-week via the DayOfWeek enum.

LocalDate mondayOnOrBeforeToday = today.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) ;

ThreeTen-Extra library

If you do want to work with ISO 8601 weeks, there is limited support available in the IsoFields class. But I recommend instead that you add the ThreeTen-Extra library to your project. That library provides additional date-time classes that complement those built into Java SE 8 and later. In particular, you get the YearWeek class.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
YearWeek yw = YearWeek.now( z ) ;

Ask for the LocalDate of a day-of-week in that week.

LocalDate ld = yw.atDay( DayOfWeek.MONDAY ) ;

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