How to calculate Date from ISO8601 week number in Java
Asked Answered
B

3

10

Is there any way of doing this: How to get dates of a week (I know week number)? for ISO 8601 week number without using any library or calender in Java?

Bolte answered 1/8, 2014 at 16:19 Comment(3)
I did not know that this "requirement" would fall in a "retarded" category. Sorry for asking. I thought this "question and answer site" was for "enthusiast programmers" I am not a experienced developer, but I am trying to develop things. Thought this would be a good place to ask questions, even, maybe, stupid ones.Bolte
Why do you want to avoid using any library/calendar? (I mean, they are there for a reason: to make your work simpler/easier) If there's a good reason, please edit your post and add it... this may become quite an interesting question if there's a good reason for it.Fortalice
Well as I said I am not a developer. I am designer working with Processing, and in the past I have worked with Processing (Java) Libraries that gave me "ambiguous errors". I came to know that was a repetition of same Class names, I changed the library and did not have the same error again. So, with that in mind, and because I am trying to develop a Processing library I wanted to avoid using libraries. Processing is also a future Javascript framework, so if i did my work without external libraries or Java calendar it would be easier in the future to port it to javascript.Bolte
P
6

UPDATE: The concepts presented here still apply, but the code is outmoded. The Joda-Time project, now in maintenance mode, advises migration to the java.time classes. See the java.time code in the Answer by Szulc.

Short Answer

DateTime dateTimeStart = new DateTime( "2003-W01-1", DateTimeZone.UTC ); // Joda-Time 2.4.
DateTime dateTimeStop = dateTimeStart.plusWeeks( 1 );

For details, read on.

Avoid j.u.Date

The old java.util.Date and java.util.Calendar classes bundled with Java are notoriously troublesome and should be avoided. Sun and its partners put a lot of neat stuff in the Java libraries, but not all of it is good. The date-time classes are perhaps the worst of it.

Furthermore those classes have weak support for ISO 8601 weeks. See this answer for details.

ISO Week Rules

You could write your own code using those classes, but I don't recommend this. The rules for calculation of ISO weeks are simple enough:

  • Week 1 has the first Thursday of the calendar year.
  • Monday is first day of week.

Joda-Time

In their place, the common replacement is a library called Joda-Time. This library includes excellent support for ISO weeks.

Simple to add to your project, just add a single .jar file.

Other Example Code

See this other answer of mine or this one for example code for getting a date-time from an ISO week number.

java.time

Java 8 has a new date-time framework, inspired by Joda-Time, found in the java.time package.

Adding Libraries

Java is built to mix libraries together. Doing so is one of the main purposes to object-oriented programming and late-binding. The comments on your question refer to the all-too-common situation where bosses irrationally or ignorantly forbid adding libraries. While there are valid reasons for such a ban, they are rare.

Forbidding adding libraries and jars in Java is like forbidding the hooking up of trailers on a fleet of vehicles equipped with a hitch.

The old date-time classes really are bad enough that many of us add Joda-Time to most any new project as a habit.

Half-Open

In date-time work, a common way to define a span of time is the "Half-Open" approach. This means the beginning is inclusive while the ending is exclusive. So a standard week begins on the first moment of a Monday, and ends on the first moment of the following Monday. Search StackOverflow.com for more discussion and examples.

Diagram of Half-Open approach to defining a week, going from start of Day 1 to start of Day 8

Textual Representation of ISO Week

The ISO 8601 standard defines ways to represent a standard week and even a day within that week.

Take the year, a hyphen, a W delimiter, and the week number represents the whole week: YYYY-Www. Add a hyphen and day-of-week number to pinpoint a day within that week: YYYY-Www-D.

Joda-Time understands this format as seen in the code example below.

Example Code

Here is some Joda-Time 2.4 code. Search StackOverflow.com for discussion and examples of these concepts. This Question and this Answer pretty much duplicate many others.

int year = 2003;
int week = 1; // Domain: 1 to 53.

// Build a String in ISO 8601 Week format: YYYY-Www-D
// Hard-coding a `1` for Monday, the standard first-day-of-week.
String input = ( String.format( "%04d", year ) + "-W" + String.format( "%02d", week ) + "-1" );

// Specify the time zone by which to define the beginning of a day.
DateTimeZone timeZone = DateTimeZone.UTC; // Or: DateTimeZone.forID( "America/Montreal" );

// Calculate beginning and ending, using Half-Open (inclusive, exclusive) approach.
DateTime dateTimeStart = new DateTime( input, timeZone );
DateTime dateTimeStop = dateTimeStart.plusWeeks( 1 );

// Use Joda-Time's tidy Interval class to represent the entire week. Use getters to access start and stop.
Interval weekInterval = new Interval( dateTimeStart, dateTimeStop );

// Is today in that week? Joda-Time has handy methods: contains, isBefore, isAfter, overlap.
boolean isTodayInThatWeek = weekInterval.contains( DateTime.now() );

Dump to console.

System.out.println( "input: " + input );
System.out.println( "dateTimeStart: " + dateTimeStart );
System.out.println( "dateTimeStop: " + dateTimeStop );
System.out.println( "interval: " + interval );
System.out.println( "isTodayInThatWeek: " + isTodayInThatWeek );

When run.

input: 2003-W01-1
dateTimeStart: 2002-12-30T00:00:00.000Z
dateTimeStop: 2003-01-06T00:00:00.000Z
interval: 2002-12-30T00:00:00.000Z/2003-01-06T00:00:00.000Z
isTodayInThatWeek: false
Parakeet answered 2/8, 2014 at 6:35 Comment(3)
Thank you for the explanation. Is this the correct way of finding the first and last date of a given year and week number? int year = 2012; int weekNumber = 8; LocalDate weekStartDate = new LocalDate().withWeekOfWeekyear(weekNumber).withYear(year); LocalDate weekEndDate = new LocalDate().withWeekOfWeekyear(weekNumber + 1).withYear(year); I am having some trouble on getting these dates in to Unix timeStamp, can you give some help with this or a link, where I can see how it is done.Bolte
@Bolte I added a code example, having discovered that Joda-Time supports the ISO standard Week string format.Parakeet
@Bolte [A] As for LocalDate, you can use them. Either use my code and translate to LocalDate, or perhaps take a more directy approach. But beware that naïve programmers tend to think that ignoring time zone makes thinks easier and simpler, but the opposite is almost always the case. If there is any chance whatsoever that you may care about sharing or comparing data with reference to any other locality, then use DateTime with time zones. [B] What about Unix timestamp? You made no mention of that in your question. Search StackOverflow for many examples of Unix timestamp conversion.Parakeet
H
6

The Java 8 / java.time way

In Java 8, you can use TemporalField combined with LocalDate::with(TemporalField, long) method for getting the correct week (of the week based year) and TemporalAdjuster combined with LocalDate::with(TemporalAdjuster) method to jump to the required day of the week, like this:

final int year = 2020;
final int weekNumber = 34;

LocalDate mondayOfWeek = LocalDate.of(year, Month.JUNE, 1)
                         .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
                         .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
                         

LocalDate sundayOfWeek = mondayOfWeek.plusDays(6);
Hubbard answered 24/8, 2015 at 15:19 Comment(1)
What is date ? new LocalDate() ?Mercola
T
3
LocalDate date = 
  LocalDate.parse("2015 53", 
     new DateTimeFormatterBuilder().appendPattern("YYYY w")
    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
    .toFormatter()));
Trap answered 23/2, 2017 at 3:12 Comment(1)
For "2022 42" I got results different to DateTimeFormatter.ISO_WEEK_DATE ... had to use: new DateTimeFormatterBuilder().appendValue(IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD).appendLiteral(" ").appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2).parseDefaulting(WeekFields.ISO.dayOfWeek(), 1).toFormatter() See also: technology.blog.gov.uk/2021/03/24/… And: #39584850Janitor

© 2022 - 2024 — McMap. All rights reserved.