1

I'm starting with an org.joda.time.DateTime and I want to output it with a timezone offset equivalent to the local time zone. It's really for the convenience of a user looking at the time with his eyes (rather than parsing it with a proper ISO8601 parser).

val tz = DateTimeZone.getDefault()
val formatter = JacksonJodaDateFormat(DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZone(tz))

What I get out is this:

2020-02-01T05:00:00+0000

What I want is this:

2020-02-01T00:00:00-0500

What it's outputting is actually correct for my time zone, but I told it .withZone(tz) and I confirmed (through the debugger) that tz is in fact America/New_York.

I'm using jodatime 2.10.2. I've also got jackson-format-jodatime in the mix here but I tried this with jackson out of the loop and it behaves the same.

The Documents say this:

When printing, this zone will be used in preference to the zone from the datetime that would otherwise be used. 

The one that would otherwise be printed is UTC, but that's not what I want it to do.

Am I interpreting what the javadocs say incorrectly?

wz2b
  • 1,017
  • 7
  • 24
  • Quick clarifications: (1) `val` is not a Java keyword - is that from Lombok? (2) What version of Java are you using? (From Java 8 onwards, `java.time` is preferred over Joda-Time - but migration may not be an option for you). – andrewJames Feb 21 '20 at 14:06
  • It's kotlin, sorry. I go back and forth between java and kotlin without even thinking about it nowadays. Yep I'm using GraalVM 11 so I definitely could use java.time instead, is that really considered preferred (i.e. joda is considered obsolete) by most people now? – wz2b Feb 21 '20 at 22:25
  • 1
    The good people behind Joda Time were instrumental in implementing `java.time`. They recommend no longer using Joda Time. See their notes [here](https://www.joda.org/joda-time/) (the "Why Joda Time" section). – andrewJames Feb 21 '20 at 22:30

1 Answers1

1

If you don't object to a Java answer (perhaps your code snippet is Kotlin?), the following will format the date string as you want, and handle time zone shifts.

To keep things simple, I also did not use the Jackson library, as you mentioned.

You can obviously replace the timezone IDs below with whatever you need for your starting point - such as "UTC". Or for the system default, using Joda-Time:

DateTimeZone defaultZone = DateTimeZone.getDefault();

Joda-Time

//
// Using Joda-Time 2.10.2:
//

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormat;

...

String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
String dateString;

DateTime dtOne = new DateTime("2020-02-21T09:30:45.678+00:00");
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);

DateTime dtTwo = dtOne.withZone(DateTimeZone.forID("America/New_York"));
dateString = fmt.print(dtTwo);   // "2020-02-21T04:30:45-0500":

DateTime dtThree = dtOne.withZone(DateTimeZone.forID("Europe/Paris"));
dateString = fmt.print(dtThree); // "2020-02-21T10:30:45+0100"

java.time

For Java 8 onwards, if you can use java.time, then withZoneSameInstant() shifts the date and time accordingly:

//
// Using java.time (Java 8 onwards):
//

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

...
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
String dateString;

DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
LocalDateTime localDateTime = LocalDateTime.parse("2020-02-21T09:30:45.123");
ZonedDateTime zonedDateTimeA = localDateTime.atZone(ZoneId.of("Europe/Paris"));

dateString = zonedDateTimeA.format(format); // "2020-02-21T09:30:45+0100"

ZonedDateTime zonedDateTimeB = zonedDateTimeA
        .withZoneSameInstant(ZoneId.of("America/New_York"));    
dateString = zonedDateTimeB.format(format); // "2020-02-21T03:30:45-0500"

For the default timezone using java.time, it's ZoneId.systemDefault().

Also, this is an amazing overview.

Edit: Use java.time instead of Joda Time

The following was mentioned in the question's comments, but needs to be stated in this answer, also:

If you can, you absolutely should use java.time over Joda Time.

From the Joda Time homepage:

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.

And from Stephen Colebourne, one of the creators of Joda Time:

I use the phraseology that java.time is "inspired by Joda-Time", rather than an exact derivation, however many concepts will be familiar.

andrewJames
  • 19,570
  • 8
  • 19
  • 51