cdeszaq
cdeszaq

Reputation: 31280

Parse Week Dates with Joda-Time?

I need to parse ISO 8601 Week dates into a format that Joda-Time can hopefully work with (eg. use for calculating the days in that week, etc.)

I've looked around a bit, but there doesn't seem to be any clear docs on how to do this.

A full DateTime instance isn't right, since I don't have an Instant in time, I only have a Partial. I can't seem to find any way to parse things into a Partial, however.

Do I need to write my own parse() method that can give me back a partial? There seem to be a couple of built-in parse methods that do this, but they all seem very specific and don't take a general format object.

Specifically, I have ISO 8601 Week dates in the following forms:

1998-W12
2005W23

What I need to do with these (ultimately) is take the week, and then convert that into a collection of the days in a given week (LocalDate JodaTime objects specifically). eg.

2013-W52 =>
2013-12-31
2014-01-01
2014-01-02
2014-01-03
2014-01-04
2014-01-05
2014-01-06

Upvotes: 0

Views: 495

Answers (2)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 78945

java.time

Shown below is a notice on the Joda-Time Home Page:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

The first day of a week is locale-sensitive

The ISO-8601 standard, followed by most of Europe, defines a week beginning with Monday. In the US, however, a week starts on Sunday.

Because of this difference, the first week of a year is different in the US and the countries following ISO-8601 standards for the first day of the week. I highly recommend checking this answer to learn more about it.

Solution using java.time API

What I need to do with these (ultimately) is take the week, and then convert that into a collection of the days in a given week ...

Since you want to find the date on the first day of the week in order to get the rest of the dates, you can define a DateTimeFormatter with the default day as 1 and use it to parse your string. Once you find day 1 of the week, you can use a loop to print all days of the week.

Demo:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.WeekFields;
import java.util.Locale;
import java.util.stream.IntStream;

class Main {
    private static final DateTimeFormatter BASIC_FORMATTER = 
                        DateTimeFormatter.ofPattern("YYYY[-]'W'ww");

    public static void main(String[] args) {
        String[] arr = { "1998-W12", "2005W23", "2013-W52" };
        Locale[] locales = { Locale.US, Locale.UK };
        for (Locale locale : locales) {
            System.out.println("===== " + locale.getDisplayCountry() + " =====");
            for (String str : arr) {
                try {
                    System.out.println("Input: " + str + " =>");
                    LocalDate date = LocalDate.parse(str, 
                                        localizedFormatter(locale));
                    System.out.println(IntStream.rangeClosed(0, 6)
                            .mapToObj(i -> date.plusDays(i))
                            .toList());
                } catch (DateTimeParseException e) {
                    System.out.println("Parsing error: " + e.getMessage());
                }
            }
        }
    }

    private static DateTimeFormatter localizedFormatter(Locale locale) {
        return new DateTimeFormatterBuilder()
                .append(BASIC_FORMATTER)
                .parseDefaulting(WeekFields.of(locale).dayOfWeek(), 1)
                .toFormatter(locale);
    }
}

Output:

========== United States ==========
Input: 1998-W12 =>
[1998-03-15, 1998-03-16, 1998-03-17, 1998-03-18, 1998-03-19, 1998-03-20, 1998-03-21]
Input: 2005W23 =>
[2005-05-29, 2005-05-30, 2005-05-31, 2005-06-01, 2005-06-02, 2005-06-03, 2005-06-04]
Input: 2013-W52 =>
[2013-12-22, 2013-12-23, 2013-12-24, 2013-12-25, 2013-12-26, 2013-12-27, 2013-12-28]
========== United Kingdom ==========
Input: 1998-W12 =>
[1998-03-16, 1998-03-17, 1998-03-18, 1998-03-19, 1998-03-20, 1998-03-21, 1998-03-22]
Input: 2005W23 =>
[2005-06-06, 2005-06-07, 2005-06-08, 2005-06-09, 2005-06-10, 2005-06-11, 2005-06-12]
Input: 2013-W52 =>
[2013-12-23, 2013-12-24, 2013-12-25, 2013-12-26, 2013-12-27, 2013-12-28, 2013-12-29]

Note:

  1. DateTimeFormatter allows you to specify an optional pattern inside a [], as shown in the above code.
  2. If you are using a Java version lower than 16, use .collect(Collectors.toList()) instead of .toList() in the above code. Check this page to learn more about it.

Learn more about the modern Date-Time API from Trail: Date Time.

Upvotes: 1

ninnemannk
ninnemannk

Reputation: 1296

JodaTime has ISO-8601 support built in. Look at the ISODateTimeFormatter. http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html

Upvotes: 2

Related Questions