In old java I can do it in that way:
System.out.println(new SimpleDateFormat(\"yyyy w\", Locale.UK).parse(\"2015 1\"));
// shows Mon Dec 29 00:00:00 CET 2014
Direct answer and solution:
System.out.println(
LocalDate.parse("2015 1",
new DateTimeFormatterBuilder().appendPattern("YYYY w")
.parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
.toFormatter()));
// output: 2014-12-29
Explanations:
a) You should use Y instead of y because you are interested in ISO-8601-week-date, not in year-of-era.
b) A calendar date cannot be formed by just giving a (week-based) year and a week-number. The day of week matters to determine the day within the specified calendar week. The predefined formatter for week-dates requires the missing day-of-week. So you need to construct a specialized parser using the builder-pattern. Then it is necessary to tell the parser what day of week is wanted - via the method parseDefaulting()
.
c) I insist (and defend JSR-310 here) on saying that the question when a week starts is not a calendar issue but a country-dependent issue. US and France (as example) use the same calendar but have different views how to define a week. ISO-8601-standard can be applied using the explicitly ISO-referring field WeekFields.ISO.dayOfWeek()
. Attention: Testing has revealed that using ChronoField.DAY_OF_WEEK
together with Locale.ROOT
does not always seem to guarantee ISO-week-behaviour as indicated in my first version of this answer (the reasons are not yet clear for me - a close view of the sources seems to be necessary to enlighten the unintuitive behaviour).
d) The java-time-package does it well - with the exception that Monday is just specified as number 1. I would have preferred the enum. Or use the enum and its method getValue()
.
e) Side notice: SimpleDateFormat
behaves leniently by default. The java-time-package is stricter and rejects to invent a missing day-of-week out of thin air - even in lenient mode (which is in my opinion rather a good thing). Software should not guess so much, instead the programmer should think more about what day-of-week is the right one. Again here: The application requirements will probably differ in US and France about the right default setting.
The accepted Answer by Meno Hochschild is correct. Here is an alternate route.
YearWeek
Use the YearWeek class in ThreeTen-Extra library. This library extends java.time with additional functionality. This particular class represents a year-week in the ISO 8601 week date system.
The factory method YearWeek.of
takes a pair of integer arguments, the week-based-year and the week number.
YearWeek yw = YearWeek.of( 2015 , 1 );
Ideally you would be using standard ISO 8601 formats for strings representing date-time values. For year-week that would be yyyy-Www the week-based-year number, a hyphen, a W
, and two digits for week number with padding zero as needed.
2015-W01
The java.time classes, and ThreeTen-Extra classes, use the standard ISO 8601 formats by default when parsing and generating strings. So life is much easier if you stick to the standard.
YearWeek yw = YearWeek.parse( "2015-W01" );
String output = yw.toString(); // 2015-W01
You have a non-standard format for numbers. So let's parse your string as two pieces, one number each, to be interpreted as int
integers.
String string = "2015 1";
String[] parts = string.split(" "); // SPACE character.
String part1 = parts[0]; // 2015
String part2 = parts[1]; // 1
The Integer
class converts such strings to int
primitive values.
int weekBasedYearNumber = Integer.parseInt( part1 ) ;
int weekNumber = Integer.parseInt( part2 ) ;
Now call that factory method.
YearWeek yw = YearWeek.of( weekBasedYearNumber , weekNumber );
LocalDate
As for first day of week, here we have been discussing the standard ISO 8601 definition of week. In that definition, Monday is always the first day, a week running from Monday-Sunday. Week # 1 contains the first Thursday of the calendar-year. In the case of 2015-W01 that Thursday would be January 1, 2015.
So, no Locale
needed.
I am not quite sure of your goal, but it seems to be extracting particular dates for days within your week. That is quite easy with the YearWeek
class and the DayOfWeek enum.
LocalDate monday = yw.atDay( DayOfWeek.MONDAY ); // 2014-12-29 start-of-week.
LocalDate friday = yw.atDay( DayOfWeek.FRIDAY ); // 2015-01-02
LocalDate sunday = yw.atDay( DayOfWeek.SUNDAY ); // 2015-01-04 end-of-week.
This can also be achieved by putting default parse value for Day of week using "ChronoField.Day_Of_Week" and setting the value as "1" as follows:
System.out.println( "Date From Year and Week : "+
LocalDate.parse("2015 1",
new DateTimeFormatterBuilder().appendPattern("YYYY w")
.parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
.toFormatter()));