11

I have two integers: year and week. I would like to construct a LocalDateTime from these two values, where the date represents the first day of the particular week in the particular year.

I already tried this:

LocalDateTime ldt = LocalDateTime.of(year, 1, 1, 0, 0).plusWeeks(week-1);

This does not give the correct result, because the first day of the year is not always the beginning of the first week of that year. I can not seem to figure out how to get the first day of the first week either.

Is there any simple way to do this with the Date and Time API in Java 8?

Note: I know I could also create a workaround with answers given here, but this seems to far-fetched. Maybe it isn't, if so, let me know!

Community
  • 1
  • 1
bashoogzaad
  • 4,611
  • 8
  • 40
  • 65
  • Week numbering within a year is locale-specific, so those two data points won't give you an exact date. AFAIK `LocalDateTime` doesn't handle that fact but `GregorianCalendar` does. – biziclop Sep 28 '15 at 11:55
  • @biziclop I think that is exactly what he want. A locale-specific week "1" - so for some guys the first 4-day-week, for others something else. – dognose Sep 28 '15 at 11:59
  • @dognose Then `GregorianCalendar` is indeed the way to go. – biziclop Sep 28 '15 at 12:00
  • Definitions of a week and week-of-year vary. Always define these terms when discussing the topic. Perhaps you meant the [standard ISO 8601 week](https://en.wikipedia.org/wiki/ISO_week_date). – Basil Bourque Aug 10 '16 at 04:43

4 Answers4

19

The following code will get a LocalDateTime and set it to the first day of the given week-of-year for the given year:

int week = 1;
int year = 2016;
WeekFields weekFields = WeekFields.of(Locale.getDefault());
LocalDateTime ldt = LocalDateTime.now()
                            .withYear(year)
                            .with(weekFields.weekOfYear(), week)
                            .with(weekFields.dayOfWeek(), 1);
System.out.println(ldt);

Note that the notion of week-of-year is locale specific. Here, I used the default Locale but you might need to use a user-provided locale.

If you want to get rid of the time part, you can add a call to truncatedTo(ChronoUnit.DAYS).

Tunaki
  • 132,869
  • 46
  • 340
  • 423
4
LocalDate ld = LocalDate.parse("2012-W48-1", DateTimeFormatter.ISO_WEEK_DATE);
Mohammad Adnan
  • 6,527
  • 6
  • 29
  • 47
Vovka
  • 599
  • 3
  • 10
  • Thanks for this answer! I think it is very similar to assylias's answer and also a bit incomplete. Maybe you could edit it to explain why it is different. – bashoogzaad Sep 28 '15 at 12:12
  • it's similar but avoid creation of extra LocalDate instance – Vovka Sep 28 '15 at 12:13
3

ThreeTen-Extra

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 YearWeek.

If by “week” you meant the standard ISO 8601 definition of a week-of-year where the week # 1 contains the first Thursday of the year, let the YearWeek class do the work for you.

int weekBasedYear = 2015;  // Not the calendar year!
int weekOfYear = 1;
YearWeek yearWeek = YearWeek.of ( weekBasedYear , weekOfYear );

You can get a date-only value represented in a LocalDate object. Specify which day-of-week you want using the DayOfWeek enum, where Monday is the first day of the week, and Sunday is last day. Remember that an ISO week always starts on a Monday and always ends on a Sunday.

LocalDate mondayOfYearWeek = yearWeek.atDay ( DayOfWeek.MONDAY );
LocalDate sundayOfYearWeek = yearWeek.atDay ( DayOfWeek.SUNDAY );

Dump to console. Note how the week starts in previous calendar year (2014) and ends in 2015, because January 1, 2015 is a Thursday so it marks ISO Week # 1. The following Sunday, January 4, 2015 concludes ISO Week # 1.

System.out.println ( "yearWeek: " + yearWeek + " starts on mondayOfYearWeek: " + mondayOfYearWeek + " and ends on sundayOfYearWeek: " + sundayOfYearWeek );

yearWeek: 2015-W01 starts on mondayOfYearWeek: 2014-12-29 and ends on sundayOfYearWeek: 2015-01-04

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 2
    this is good but problem is using another dependency. I wish such intuitive API gets added in jdk itself. – Mohammad Adnan Oct 14 '16 at 05:02
  • 1
    @MohammadAdnan *ThreeTen-Extra* is led by the same man, [Stephen Colebourne](https://stackoverflow.com/users/38896/jodastephen), who leads the *java.time* classes, their specification in JSR 310, and their predecessor *Joda-Time*. The *ThreeTen-Extra* project is a proving ground for classes that may indeed join the *java.time* classes someday. I suggest you make enjoy their usefulness now. – Basil Bourque Mar 18 '19 at 00:47
2

You could try to parse a string representation of the day you are interested in:

private static final DateTimeFormatter YEAR_WEEK = DateTimeFormatter.ofPattern("YYYY-w-e", Locale.getDefault());

public static LocalDate fromYearWeek(int year, int week) {
  return LocalDate.parse(year + "-" + week + "-1", YEAR_WEEK);
}

If you need a LocalDateTime, you can then use localDate.atTime(...) or localDate.atStartOfDay() for example.

assylias
  • 321,522
  • 82
  • 660
  • 783