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.

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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.
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()) 

5 Comments

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.
@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.
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.
@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.
From what I remember you have to go to the Clock class and call getZone()
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.

1 Comment

I can't find class ZoneId in version 0.6.3 of the JSR-310 reference implementation.
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 ); } 

3 Comments

I really don't see the need to resort to this old approach.
@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.
Date has a method for this as well, Date.from(instant). Nwm, See your strange version now

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.