ISO-8601 week data representation for basic temporal operations

121 Views Asked by At

I've got week data in ISO 8601 format. E.g.:

weekA = '2012-W48'
weekB = '2013-W03'

Is there a class in Java that can represent those weeks and supports basic temporal operations? I tried LocalDate.parse("2012-W48",DateTimeFormatter.ISO_WEEK_DATE); but this throws an error because this is a week, not an actual date (i.e. the day in the week is missing). Similar to the LocalDate class, I'd like to be able to do some basic temporal operations such as:

  • weekA.isBefore(weekB) returns true if weekA is before weekB
  • weeksBetween(weekA,weekB) returns the number of weeks between the two week dates, i.e. weekB-weekA in weeks.

Ideally I'd only use standard Java classes (Java >= 11).

2

There are 2 best solutions below

0
Arvind Kumar Avinash On BEST ANSWER

Using standard library

The original solution (check below) was using an external library. The credit for this solution goes to user85421. The idea is to parse the given string into a LocalDate by defaulting the day of the week to day-1.

public class Main {
    public static void main(String[] args) {
        String strWeekA = "2012-W48";
        String strWeekB = "2013-W03";

        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                .appendPattern("YYYY-'W'ww")
                .parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
                .toFormatter();

        LocalDate date1 = LocalDate.parse(strWeekA, dtf);
        LocalDate date2 = LocalDate.parse(strWeekB, dtf);

        System.out.println(WEEKS.between(date1, date2));
    }
}

Output:

7

Online Demo

Using an external library (original solution)

You can use the ThreeTen-Extra library for your requirements.

You can use YearWeek, and its isBefore and isAfter methods.

You can use java.time.temporal.ChronoUnit#between to calculate the amount of time between two YearWeek objects. Alternatively, you can use YearWeek#until to get the same result.

Given below is the Maven dependency for it:

<dependency>
  <groupId>org.threeten</groupId>
  <artifactId>threeten-extra</artifactId>
  <version>1.7.2</version>
</dependency>

Demo:

import org.threeten.extra.YearWeek;
import static java.time.temporal.ChronoUnit.WEEKS;

public class Main {
    public static void main(String[] args) {
        String strWeekA = "2012-W48";
        String strWeekB = "2013-W03";
        YearWeek weekA = YearWeek.parse(strWeekA);
        YearWeek weekB = YearWeek.parse(strWeekB);
        System.out.println(weekA.isBefore(weekB));
        System.out.println(WEEKS.between(weekA, weekB));
        System.out.println(weekA.until(weekB, WEEKS));
    }
}

Output:

true
7
7
0
Gladitor On

In Java, there isn't a direct class for representing ISO week dates like 2012-W48 in the java.time package without specifying the day of the week. However, you can work around this by appending a day of the week (like -1 for Monday) to your week strings and then using LocalDate with DateTimeFormatter.ISO_WEEK_DATE. Once you have LocalDate objects, you can perform the operations you mentioned. Here's how you can achieve this:

public class WeekOperations {

    public static void main(String[] args) {
        String weekA = "2012-W48";
        String weekB = "2013-W03";
        
        LocalDate dateA = parseWeek(weekA);
        LocalDate dateB = parseWeek(weekB);
        
        System.out.println("Week A is before Week B: " + dateA.isBefore(dateB));
        System.out.println("Weeks between Week A and Week B: " + weeksBetween(dateA, dateB));
    }
    
    private static LocalDate parseWeek(String week) {
        return LocalDate.parse(week + "-1", DateTimeFormatter.ISO_WEEK_DATE);
    }
    
    private static long weeksBetween(LocalDate start, LocalDate end) {
        return ChronoUnit.WEEKS.between(start, end);
    }
}

Please note that this approach assumes you're working with the first day of each ISO week. If you need to represent the entire week or perform operations on a different basis, you might need to adjust the logic accordingly. However, for comparison and difference calculation as you described, this method should work well.