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)
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
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:
+00:00
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
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
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
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.
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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With