9

I am reading data from Wikidata. They represent their point in time property, P585 using ISO 8601 spec. However, the same beings with a +.

If I were using Joda then converting the String to joda dateTime would have been very simple.

new DateTime(dateTime, DateTimeZone.UTC);

However, when I do LocalDateTime.parse("+2017-02-26T00:00:00Z") I get an error saying can't parse the character at index 0. Is there a reason for this in Java 8. Joda does it pretty easily without any errors.

I also tried LocalDateTime.parse("+2017-02-26T00:00:00Z", DateTimeFormatter.ISO_DATE_TIME) but in vain.

How do we get around the Plus sign without having to remove it by string manipulation?

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
dhamechaSpeaks
  • 127
  • 1
  • 1
  • 6

3 Answers3

14

Java's DateTimeFormatter class may be of help. Here is some sample code that I believe addressses your problem (or at least gives you something to think about):

class DateTimeTester {
  ---
  public static void main(String[] args) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("+yyyy-MM-dd'T'HH:mm:ss'Z'")
        .withZone(ZoneId.of("UTC"));
    LocalDateTime date = LocalDateTime.parse("+2017-02-26T01:02:03Z", formatter);
    System.out.println(date);
  }
}

Refer to the section called Patterns for Formatting and Parsing in the javadoc for DateTimeFormatter for details about the format-string passed to DateTimeFormatter.ofPattern().

Something to note:

Wikidata's list of available data types says about the time data type:

"explicit value for point in time, represented as a timestamp resembling ISO 8601, e.g. +2013-01-01T00:00:00Z. The year is always signed and padded to have between 4 and 16 digits.".

So Wikidata's time data type only resembles ISO 8601.

If your code needs to handle negative years (before year 0), you will need to adjust my suggested solution accordingly.

StvnBrkdll
  • 3,924
  • 1
  • 24
  • 31
  • Thanks for your answer. This makes sense. I expected baba.time to take care of this automatically without the DataFormatter just like how joda.time does. Nevertheless thanks for the explanation and answer. How do I mark this as a correct answer? – dhamechaSpeaks Feb 03 '17 at 03:30
  • 3
    I think you could replace those format strings with DateTimeFormatter.ISO_LOCAL_DATE_TIME – user2725919 Oct 19 '18 at 17:07
  • 1
    @user2725919 No that will not work. It neither takes the leading `+` nor the trailing `Z` into account. I get `DateTimeParseException: Text '+2017-02-26T01:02:03Z' could not be parsed at index 0`. – Ole V.V. Feb 11 '23 at 21:19
5

Unfortunately, the accepted answer is wrong for three reasons:

  1. The given date-time string +2017-02-26T00:00:00Z does not represent a LocalDateTime. It represents an OffsetDateTime.
  2. It uses a + sign with the pattern which means the pattern will fail to parse a date-time with a negative year.
  3. 'Z' is not the same as Z.

You can create the required DateTimeFormatter using the DateTimeFormatterBuilder as shown below:

class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = new DateTimeFormatterBuilder()
                .appendValue(ChronoField.YEAR, 4, 4, SignStyle.ALWAYS)
                .appendPattern("-MM-dd'T'HH:mm:ssXXX")
                .toFormatter(Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse("+2017-02-26T00:00:00Z", parser);
        System.out.println(odt);

        // If you want a LocalDateTime, you can get it from `odt`
        LocalDateTime ldt = odt.toLocalDateTime();
        System.out.println(ldt);
    }
}

Output:

2017-02-26T00:00Z
2017-02-26T00:00

ONLINE DEMO

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

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

A quick solution can be :

LocalDateTime.parse(yourDate, DateTimeFormatter.ISO_DATE_TIME);

Don't forget to manage the DateTimeParseException in the case of a non supported date format

Vincent Kelleher
  • 492
  • 2
  • 6
  • 12
  • 1
    This doesn’t seem to work. With the string from the question, `"+2017-02-26T00:00:00Z"`, I get `DateTimeParseException: Text '+2017-02-26T00:00:00Z' could not be parsed at index 0`. – Ole V.V. Feb 11 '23 at 21:15
  • 1
    Indeed, I didn't notice the `+` sign in front of the year after reading the ISO8601 in the title You would need one of the custom `DateTimeFormatter`s above. – Vincent Kelleher Feb 12 '23 at 10:54