27

How do I format a javax.time.Instant as a string in the local time zone? The following translates a local Instant to UTC, not to the local time zone as I was expecting. Removing the call to toLocalDateTime() does the same. How can I get the local time instead?

public String getDateTimeString( final Instant instant )
{
    checkNotNull( instant );
    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
    DateTimeFormatter formatter = builder.appendPattern( "yyyyMMddHHmmss" ).toFormatter();
    return formatter.print( ZonedDateTime.ofInstant( instant, TimeZone.UTC ).toLocalDateTime() );
}

Note: We're using the older version 0.6.3 of the JSR-310 reference implementation.

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174

4 Answers4

41

Answering this question wrt the nearly finished JDK1.8 version

DateTimeFormatter formatter =
  DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault());
return formatter.format(instant);

The key is that Instant does not have any time-zone information. Thus it cannot be formatted using any pattens based on date/time fields, such as "yyyyMMddHHmmss". By specifying the zone in the DateTimeFormatter, the instant is converted to the specified time-zone during formatting, allowing it to be correctly output.

An alternative approach is to convert to ZonedDateTime:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
return formatter.format(ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()));

Both approaches are equivalent, however I would generally choose the first if my data object was an Instant.

JodaStephen
  • 60,927
  • 15
  • 95
  • 117
  • Thank you for the answer. I have little doubt that it's correct, but I'll have to wait for the next opportunity to apply this solution in place of the one that I implemented. I'd also have to wait until our team replaces version 0.6.3 of JSR-310 with a more recent version or replace JDK 6 with JDK 8. – Derek Mahar Apr 09 '13 at 22:09
6

Why would you expect it to use the local time zone? You're explicitly asking for UTC:

ZonedDateTime.ofInstant(instant, TimeZone.UTC)

Just specify your local time zone instead:

ZonedDateTime.ofInstant(instant, TimeZone.getDefault())
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I was expecting `toLocalDateTime()` to convert it to the local or default time zone. Apparently, I misunderstand what `toLocatlDateTime()` does. I thought I could create a `LocalDateTime`, but this class has no method that converts an `Instant` to a `LocalDateTime`. – Derek Mahar Dec 06 '12 at 21:07
  • 2
    @DerekMahar: Local doesn't mean what you think it does, basically. It just means a date and time which isn't associated with any particular time zone. So for example, all round the world, the New Year starts at midnight on January 1st. For any particular year, that's a LocalDateTime - one which occurs at different *instants* for different time zones. – Jon Skeet Dec 06 '12 at 21:11
  • Unfortunately, JSR-310 doesn't use `java.util.TimeZone` and class `javax.time.calendar.TimeZone` in version 0.6.3 of JSR-310 doesn't appear to have method `getDefault()` or any similar method. – Derek Mahar Dec 06 '12 at 21:20
  • @DerekMahar: Right - I tried to look for the documentation, but as that's an old version, I couldn't find it. I'm sure there's a way of getting the system default time zone *somehow*. – Jon Skeet Dec 06 '12 at 22:00
  • 1
    From what I remember you have to go to the Clock class and call getZone() – JodaStephen Dec 14 '12 at 15:36
1

The question was about version 0.6.3 of the JSR-310 reference implementation, long before the arrival of Java 8 and the new date library


I gave up on JSR-310 classes DateTimeFormatter and ZonedDateTime and instead resorted to old fashioned java.util.Date and java.text.SimpleDateFormat:

public String getDateTimeString( final Instant instant )
{
    checkNotNull( instant );
    DateFormat format = new SimpleDateFormat( "yyyyMMddHHmmss" );
    Date date = new Date( instant.toEpochMillisLong() );
    return format.format( date );
}
miken32
  • 42,008
  • 16
  • 111
  • 154
Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • 2
    I really don't see the need to resort to this old approach. – Simon Forsberg Oct 21 '14 at 12:03
  • @SimonAndréForsberg: Unfortunately I had to because we were using 0.6.3 of the JSR-310 reference implementation. Fortunately, though our product still uses Java 7, we've since moved on to the latest JSR-310 that appears in Java 8. – Derek Mahar Oct 30 '14 at 16:28
  • Date has a method for this as well, Date.from(instant). Nwm, See your strange version now – softarn Dec 01 '15 at 13:03
1

Try this:

String dateTime = DateTimeFormatter.ISO_ZONED_DATE_TIME.format(
    ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
);

This gives:

2014-08-25T21:52:07-07:00[America/Los_Angeles]

You can change the format by using something other than DateTimeFormatter.ISO_ZONED_DATE_TIME as the formatter. DateTimeFormatter has a bunch of predefined formatters, or you can define your own.

Luke Hutchison
  • 8,186
  • 2
  • 45
  • 40