Michael
Michael

Reputation: 719

Joda ISODateTimeFormat not using timezone in String

I have a two part issue, or maybe its two different ways to solve this. I receive an ISO string like 2015-11-17T17:10:24-0800. The end goal is to display the string as 11/17/15 5:10 PM in some HTML generated by some Freemarker. The string I receive could be in any timezone, but I always need to display the string in its local timezone as shown above. Currently, our code was just taking the string and passing it into the template and coverting as such:

<#assign mydate = obj.mydate?datetime("yyyy-MM-dd'T'HH:mm:ssz")?string.short>

This is no longer good since I believe Freemarker is using the system's local timezone and now we are getting more than one timezone. I see there is an iso method in freemarker. So I try

<#assign order_date = order.order_date?iso("yyyy-MM-dd'T'HH:mm:ssz")>

but I keep getting error:

For "?iso" left-hand operand: Expected a date, but this evaluated to a string

Ok I need a date. Working with Joda, I try and create a datetime object by:

DateTime dateTime = ISODateTimeFormat.dateTimeNoMillis().parseDateTime("2015-11-17T17:10:24-0800");

But that appears to use my local timezone as well and shows 2015-11-17T20:10:24.000-05:00. I know I could do withZone(...) but I dont know the zone other than the -0800 or whatever zone is passed at the end of the string. So I'm at a loss of what to do now. Oh, and I cannot change the format of the string I receive.

Upvotes: 4

Views: 1202

Answers (3)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79075

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.

In March 2014, Java 8 introduced the modern, java.time date-time API which supplanted the error-prone legacy, java.util date-time API. Any new code should use the java.time API*.

Solution using modern date-time API

The string, 2015-11-17T17:10:24-0800 contains a ZoneOffset of -08:00, rather than a time zone. Therefore, it should be parsed into an OffsetDateTime. Had it contained a ZoneId e.g. ZoneId of Pacific/Pitcairn, a ZonedDateTime would have been the appropriate object to parse into.

Once you have parsed it into an OffsetDateTime, you can format it as desired.

If you want to convert it into an OffsetDateTime with another ZoneOffset, you can do so using OffsetDateTime#withOffsetSameInstant.

Demo:

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ");
        OffsetDateTime odt = OffsetDateTime.parse("2015-11-17T17:10:24-0800", parser);
        System.out.println(odt);

        // Print it in a custom format
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/uu");
        String odtFormatted = odt.format(formatter);
        System.out.println(odtFormatted);

        // Convert it into an OffsetDateTime with another ZoneOffset
        // A sample ZoneOffset
        ZoneOffset zoneOffset = ZoneOffset.of("-04:00");
        OffsetDateTime odtWithAnotherOffset = odt.withOffsetSameInstant(zoneOffset);
        System.out.println(odtWithAnotherOffset);
    }
}

Output:

2015-11-17T17:10:24-08:00
11/17/15
2015-11-17T21:10:24-04:00

Online Demo

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


* If you are receiving an instance of java.util.Date, convert it tojava.time.Instant, using Date#toInstant and derive other date-time classes of java.time from it as per your requirement.

Upvotes: 2

Roman
Roman

Reputation: 6656

DateTime dateTime = ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed().parseDateTime("2015-11-17T17:10:24-0800");

This will create a DateTime with a fixed timezone offset of -08:00.

Upvotes: 5

bszeliga
bszeliga

Reputation: 138

May require a little more work, but you could always use the DateTimeFormatterBuilder to create your own custom display for the Date Time. This way you could drop the TimeZone if you care to and render it for within that TimeZone or render locally.

Upvotes: 0

Related Questions