6

I am writing a stock program that (so far) gets the data from "Markit on Demand" through a request such as this:

http://dev.markitondemand.com/Api/v2/Quote/xml?symbol=aapl

This returns the data in xml, with various measures of the stock (Symbol, name, last price, change, time stamp, etc).

I am having trouble creating a DateTimeFormatter in Java 8 to make the timestamp.

One example of a timestamp:

Fri Jul 18 15:59:00 UTC-04:00 2014

So far the pattern I have is as follows:

EEE MMM d HH:mm:ss OOOO yyyy

As I'm sure some of you can spot, I am having trouble with the offset.

From the Documentation:

Offset X and x: This formats the offset based on the number of pattern letters. One letter outputs just the hour, such as '+01', unless the minute is non-zero in which case the minute is also output, such as '+0130'. Two letters outputs the hour and minute, without a colon, such as '+0130'. Three letters outputs the hour and minute, with a colon, such as '+01:30'. Four letters outputs the hour and minute and optional second, without a colon, such as '+013015'. Five letters outputs the hour and minute and optional second, with a colon, such as '+01:30:15'. Six or more letters throws IllegalArgumentException. Pattern letter 'X' (upper case) will output 'Z' when the offset to be output would be zero, whereas pattern letter 'x' (lower case) will output '+00', '+0000', or '+00:00'.

Offset O: This formats the localized offset based on the number of pattern letters. One letter outputs the short form of the localized offset, which is localized offset text, such as 'GMT', with hour without leading zero, optional 2-digit minute and second if non-zero, and colon, for example 'GMT+8'. Four letters outputs the full form, which is localized offset text, such as 'GMT, with 2-digit hour and minute field, optional second field if non-zero, and colon, for example 'GMT+08:00'. Any other count of letters throws IllegalArgumentException.

Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.

// String rawDate = Fri Jul 18 15:59:00 UTC-04:00 2014   
DateTimeFormatter PARSER_PATTERN = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss 'UTC'XXX yyyy");
ZonedDateTime timeStamp = ZonedDateTime.parse(rawDate, PARSER_PATTERN);

This works, but I am curious why (in place of the 'UTC'XXX) OOOO doesn't work.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
Will Pike
  • 281
  • 4
  • 17
  • Could there be a bug in Java 8 parsing of format pattern OOOO? I get a `StringIndexOutOfBoundsException` when trying to parse a string where offset is given as `GMT+02:00` at the end of the string. In Java 9 the same parsing works smoothly, which is why I suspect a bug in Java 8. – Ole V.V. Jul 26 '17 at 02:53
  • From [the bug database: java.time.format.DateTimeFormatter can't parse localized zone-offset](https://bugs.openjdk.java.net/browse/JDK-8154050). “The DateTimeFormatter fails to parse its own output for format strings containing "O".” – Ole V.V. Jul 26 '17 at 03:01
  • In my Java 9 it works with `GMT-04:00` but I still cannot make it work with `UTC-04:00`. Don’t know why. – Ole V.V. Jul 26 '17 at 03:13

2 Answers2

1

I decided to use a String 'UTC' because the timestamp is always given in the form of "UTC+00:00".

The final pattern I came up with to match the zoned date time:

Fri Jul 18 15:59:00 UTC-04:00 2014

is EEE MMM d HH:mm:ss 'UTC'XXX yyyy

Will Pike
  • 281
  • 4
  • 17
  • Seems reasonable, but this would match an `OffsetDateTime`, not a `ZonedDateTime`. – Matt Johnson-Pint Jul 20 '14 at 17:05
  • However, it doesn't really answer your original question as to why `OOOO` doesn't work. According to the docs, it should. Just above the section [on the same page](http://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns), it shows an example of `UTC-08:00`. – Matt Johnson-Pint Jul 20 '14 at 17:09
  • That's why I was a little confused...I answered my initial question about what it should be, but not why `OOOO` didn't work. – Will Pike Jul 20 '14 at 17:10
  • Perhaps if you edit the original question to remove the bits about your stock program and just show the Java code that uses the `DateTimeFormatter` with this particular input string, someone more familiar than I can answer the question as to why `OOOO` doesn't work. But good job figuring out the workaround. – Matt Johnson-Pint Jul 20 '14 at 17:12
1

Do not use a fixed text for the timezone:

Do not use a fixed text (e.g. 'UTC') for the timezone because that approach may fail for other locales.

You can parse your Date-Time string using the pattern, E MMM d H:m:s VV u.

Demo:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "Fri Jul 18 15:59:00 UTC-04:00 2014";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM d H:m:s VV u", Locale.ENGLISH);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);
    }
}

Output:

2014-07-18T15:59-04:00[UTC-04:00]

ONLINE DEMO


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

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • 2
    Brilliant! I tested on Java 8, 9 and 11. It works.Both with `UTC-04:00` and `GMT-04:00`. – Ole V.V. Jul 10 '21 at 14:05
  • 1
    I like this a lot. It works because `VV` resolves the ZoneId ([per the format patterns table](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns)) and by definition of ZoneId, "UTC", "GMT", and "UT" are recognized as prefixes of an offset-style ID (per [third paragraph under "Time-zone IDs" here](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html)). Be aware that the exact same format string would work with any valid ZoneID, such as `America/Los_Angeles` in the input string. – Matt Johnson-Pint Jul 12 '21 at 17:47