Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: How to get current date in ISO 8601 SECOND format

I need to get the current date in ISO 8601 with SS milliseconds and HH:MM timezone

Complete date plus hours, minutes, seconds and a decimal fraction of a second: YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)

see: http://www.w3.org/TR/NOTE-datetime

i tried different approaches, but i cannot get the correct milliseconds & timezone digits:

DateFormat df=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSZZ");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
df.format(new Date());

JAVA result: 2012-11-24T21:19:27.758+0000

Apache result: 2012-11-24T21:19:27.758+00:00 (Apache Commons FastDateFormat)

like image 514
marcolopes Avatar asked Nov 24 '12 21:11

marcolopes


2 Answers

Actually there is a class in JDK that handles parsing and formatting ISO8601:

import javax.xml.bind.DatatypeConverter;

DatatypeConverter.printDateTime(new GregorianCalendar())
//2012-11-24T22:42:03.142+01:00
like image 70
Tomasz Nurkiewicz Avatar answered Oct 13 '22 22:10

Tomasz Nurkiewicz


tl;dr

Current moment, UTC

Use java.time.Instant to capture the current moment in a resolution as fine as nanoseconds.

Instant.now()  // Capture the current moment in UTC, with a resolution as fine as nanoseconds. Typically captured in microseconds in Java 9 and later, milliseconds in Java 8.
.toString()    // Generate a `String` representing the value of this `Instant` in standard ISO 8601 format.

2018-01-23T12:34:56.123456Z

The Z on the end:

  • means UTC,
  • is equivalent to +00:00 offset,
  • is pronounced “Zulu”, and
  • is defined by the ISO 8601 standard as well as other arenas such as military.

Current moment, specific offset

If for some unusual reason you must adjust into a specific offset-from-UTC, use OffsetDateTime, passing a ZoneOffset.

OffsetDateTime.now(          // Capture the current moment.
    ZoneOffset.ofHours( 1 )  // View the current moment adjusted to the wall-clock time of this specific offset-from-UTC. BTW, better to use time zones, generally, than a mere offset-from-UTC.
)
.toString()                  // Generate a `String` in standard ISO 8601 format.

2018-07-08T21:13:10.723676+01:00

Current moment, truncated to millis

For milliseconds resolution, truncate. Specify resolution by ChronoUnit enum.

OffsetDateTime.now( 
    ZoneOffset.ofHours( 1 ) 
)
.truncatedTo(               // Lop off finer part of the date-time. We want to drop any microseconds or nanoseconds, so truncate to milliseconds. Using the immutable objects pattern, so a separate new `OffsetDateTime` object is generated based on the original object’s values.
    ChronoUnit.MILLIS       // Specify your desired granularity via `ChronoUnit` enum.
)
.toString()                

2018-07-08T21:13:10.723+01:00

java.time

The java.time framework built into Java 8 and later uses ISO 8601 be default when parsing or generating textual representations of date-time values.

An Instant is a moment on the timeline in UTC with a resolution of nanoseconds.

Instant instant = Instant.now();

The current moment is captured with a resolution of milliseconds in Java 8, and in Java 9 and later, typically a resolution of microseconds depending on capabilities of host hardware clock and OS. If you specifically want milliseconds resolution, truncate any microseconds or nanoseconds.

Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;

But you want a specific offset-from-UTC. So specify a ZoneOffset to get a OffsetDateTime.

ZoneOffset offset = ZoneOffset( "+01:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , offset );

Again, truncate if you specifically want milliseconds resolution rather than microseconds or nanoseconds.

odt = odt.truncatedTo( ChronoUnit.MILLIS ) ;  // Replace original `OffsetDateTime` object with new `OffsetDateTime` object based on the original but with any micros/nanos lopped off.

To generate your ISO 8601 string, simply call toString.

String output = odt.toString();

Dump to console. Note in the output how the hour rolled forward as an adjustment to the +01:00 offset, and that even rolled over midnight so the date changed from the 12th to the 13th.

System.out.println ( "instant: " + instant + " | offset: " + offset + " | odt: " + odt );

instant: 2016-04-12T23:12:24.015Z | offset: +01:00 | odt: 2016-04-13T00:12:24.015+01:00

Zoned

By the way, it is better to use a time zone (if known) than just a mere offset. A time zone a history of the past, present, and future changes in offset used by the people of a particular region.

In java.time that means applying a ZoneId to get a ZonedDateTime.

ZoneId zoneId = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Or skip Instant, as a shortcut.

ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;

Generate a String representing textually the value of that ZonedDateTime object. The format used by default is standard ISO 8601 format wisely extended to append the name of the zone in square brackets.

zdt.toString(): 2018-07-08T22:06:58.780923+02:00[Europe/Paris]

For other formats, use the DateTimeFormatter class.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

like image 31
Basil Bourque Avatar answered Oct 14 '22 00:10

Basil Bourque