415

What is the most elegant way to get ISO 8601 formatted presentation of the current moment, UTC? It should look like: 2010-10-12T08:50Z.

Example:

String d = DateFormat.getDateTimeInstance(DateFormat.ISO_8601).format(date);
Saikat
  • 14,222
  • 20
  • 104
  • 125
yegor256
  • 102,010
  • 123
  • 446
  • 597
  • 3
    https://svn.apache.org/repos/asf/commons/dormant/feedparser/trunk/src/java/org/apache/commons/feedparser/tools/ISO8601DateParser.java – marcolopes Nov 24 '12 at 20:56
  • 5
    @marcolopes Beware, that use of a `private static SimpleDateFormat` is not thread safe. – vegemite4me Sep 05 '14 at 08:35
  • Possible duplicate of [Converting ISO 8601-compliant String to java.util.Date](http://stackoverflow.com/questions/2201925/converting-iso-8601-compliant-string-to-java-util-date) – Anthony Nov 12 '15 at 20:22
  • 1
    Similar to [this other Question](http://stackoverflow.com/q/35453198/642706), but that one truncates to whole second whereas this Question truncates to whole minute. – Basil Bourque Feb 17 '16 at 21:33

24 Answers24

352

Use SimpleDateFormat to format any Date object you want:

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

Using a new Date() as shown above will format the current time.

Mr. Lance E Sloan
  • 3,297
  • 5
  • 35
  • 50
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 8
    @Joachim The negative side of this "standard" approach is that I have to have many instances of `"yyyy-MM-dd'T'HH:mmZ"` in my application, every time I need an ISO-8601 formatted date. With JodaTime, as I see, I can use a pre-defined formatter `ISODateTimeFormat`, which does this job for me.. – yegor256 Oct 12 '10 at 12:18
  • 9
    @Joachim, `Z` is valid pattern in SimpleDateFormat, rather do this: `yyyy-MM-dd'T'HH:mm'Z'`. – Buhake Sindi Oct 12 '10 at 12:43
  • @Gentleman: I know, I should have noted that. Depending on whether the expected result is always `Z` or the actual timezone (which needs some further tweakng) the `Z` in the pattern must be quoted or not. – Joachim Sauer Oct 12 '10 at 13:09
  • 34
    -1 This gives you the date/time in the current timezone - not UTC. Carlos' answer includes the necessary UTC code. – Scott Rippey Mar 30 '12 at 16:15
  • 1
    @TomTresansky a common approach to this is to keep the the SDF in a ThreadLocal: public static final ThreadLocal FORMAT_TL = new ThreadLocal() { protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ"); } }; – Asaf Apr 30 '13 at 07:26
  • 20
    I just fixed the timezone mistake - since it is the accepted answer I think it was the right thing to do. – BoD Aug 16 '13 at 22:22
  • 1
    If you want the current time zone use TimeZone tz = TimeZone.getDefault(); instead – dev4life Jun 24 '14 at 19:15
  • 2
    The Z needs to be quoted like "yyyy-MM-dd'T'HH:mm'Z'" – Kimball Robinson Oct 13 '15 at 22:26
  • @TomTresansky, so instead of global instance, have a global method that returns instances. – Paul Draper Feb 08 '16 at 08:33
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). Specifically, see `Instant` class. – Basil Bourque Apr 10 '18 at 20:28
  • @KimballRobinson No, if you put singe-quotes around the `Z` you are ignoring an important fact, the fact that this date-time is in UTC time zone. In other words, **your advice results in data loss**. The real solution is using modern *java.time* classes rather than these troublesome old legacy date-time classes. `Instant.now().toString()` – Basil Bourque May 04 '18 at 23:38
  • FYI 'Z' is a valid timezone descriptor in ISO8601. SimpleDateFormat uses 'X' to describe ISO8601 format timezones, so "yyyy-MM-dd'T'HH:mmX" would parse the date correctly. – heisbrandon Sep 05 '18 at 16:17
  • This returns date time like 2020-02-01T07:13:03Z but I want the Z to be replaced with '+00:00'. How to achieve this? – Ajithkumar_sekar Feb 28 '20 at 08:44
260

Java 8 Native

java.time makes it simple since Java 8. And thread safe.

ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_INSTANT )

Result: 2015-04-14T11:07:36.639Z

You may be tempted to use lighter Temporal such as Instant or LocalDateTime, but they lacks formatter support or time zone data. Only ZonedDateTime works out of the box.

By tuning or chaining the options / operations of ZonedDateTime and DateTimeFormatter, you can easily control the timezone and precision, to a certain degree:

ZonedDateTime.now( ZoneId.of( "Europe/Paris" ) )
             .truncatedTo( ChronoUnit.MINUTES )
             .format( DateTimeFormatter.ISO_DATE_TIME )

Result: 2015-04-14T11:07:00+01:00[Europe/Paris]

Refined requirements, such as removing the seconds part, must still be served by custom formats or custom post process.

.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) // 2015-04-14T11:07:00
.format( DateTimeFormatter.ISO_LOCAL_DATE ) // 2015-04-14
.format( DateTimeFormatter.ISO_LOCAL_TIME ) // 11:07:00
.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm" ) ) // 2015-04-14 11:07

For Java 6 & 7, you may consider back-ports of java.time such as ThreeTen-Backport, which also has an Android port. Both are lighter than Joda, and has learned from Joda's experience - esp. considering that java.time is designed by Joda's author.

Sheepy
  • 17,324
  • 4
  • 45
  • 69
  • 11
    Good answer. Notice the good habit of *explicitly* specifying a time zone rather than relying implicitly on the JVM’s current default time zone. You may specify [a particular time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) if desired, such as `ZoneId.of( "America/Montreal" )`. – Basil Bourque Feb 17 '16 at 21:51
  • 3
    Instant allows to format it in ISO 8601 format by just calling .toString() method: `return DateTimeFormatter.ISO_INSTANT.format(this);` – VadymVL Nov 07 '17 at 14:39
  • This is best because you avoid the default. – Christophe Roussy Apr 03 '18 at 12:18
  • 9
    Warning: The solution for Java 8 using ISO_INSTANT has an annoying quirk. When the milliseconds happen to be 0 they are not included in the output. This is allowed according to the ISO 8601 standard but many libraries and parsers in other languages are not that forgiving. If it is necessary to always include the zeros use this instead: DateTimeFormatter ISO_8601 = ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX").withZone(UTC); – jurgen Jul 24 '18 at 20:57
  • 2
    After switching from Java 8 to 11, I see `DateTimeFormatter.ISO_INSTANT` and `DateTimeFormatter.ISO_DATE_TIME` using 6 digits after the seconds, as opposed to 3, which is no longer picked up by Spring's `@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)`. – DanielM Jan 23 '20 at 11:29
234

For systems where the default Time Zone is not UTC:

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

The SimpleDateFormat instance may be declared as a global constant if needed frequently, but beware that this class is not thread-safe. It must be synchronized if accessed concurrently by multiple threads.

EDIT: I would prefer Joda Time if doing many different Times/Date manipulations...
EDIT2: corrected: setTimeZone does not accept a String (corrected by Paul)

Ali Dehghani
  • 46,221
  • 15
  • 164
  • 151
user85421
  • 28,957
  • 10
  • 64
  • 87
  • 19
    This format isn't a constant anywhere in some built in library? – Daniel Kaplan Jun 10 '14 at 22:44
  • 1
    There are two different packages for 'DateFormat', remember to use 'import java.text.DateFormat' – dev4life Jun 24 '14 at 19:12
  • 3
    If you want the current time zone use TimeZone tz = TimeZone.getDefault(); instead – dev4life Jun 24 '14 at 19:15
  • You should *not* quote the 'Z' in the format since that makes it logically insignificant. If the TimeZone is UTC as in the example above then an unquoted Z will only result in a Z in the output...however if the TimeZone is not UTC then the Z will still be output as a literal implying UTC when the time may not be. If a consuming system reads the Z as UTC but the time is not the time will be shifted. Conversely if a parser uses the quoted Z without setting the TimeZone it will parse UTC times as local times (again shifting). This quote isn't needed if the TZ is set but is dangerous if it isn't. – Matt Whipple Jun 13 '16 at 18:50
  • @MattWhipple - but if you use an unquoted Z the result will be something like `2016-06-14T13:56+0000` - the question is asking for something like `2016-06-14T13:56Z` – user85421 Jun 14 '16 at 14:00
  • I was thinking of `X` which will deliver the desired behavior and should be preferred to ensure consistency. If for some reason it isn't due to an ancient version of Java or similar then the use of the literal should come with very prominent warnings about the necessity to set the timezone. – Matt Whipple Jun 14 '16 at 14:06
  • @MattWhipple - ahh, but the `X` format was not available at the time this question/reply was posted - Java 6... As I remember it was included starting with Java 7 (2011?) Now it would be better to use the Date-Time API – user85421 Jun 14 '16 at 14:47
201

As of Java 8 you can simply do:

Instant.now().toString();

From the java.time.Instant docs:

now

public static Instant now()

Obtains the current instant from the system clock.

This will query the system UTC clock to obtain the current instant.

 

toString

public String toString()

A string representation of this instant using ISO-8601 representation.

The format used is the same as DateTimeFormatter.ISO_INSTANT.

David Moles
  • 48,006
  • 27
  • 136
  • 235
  • 24
    This is the right answer, and it's a scandal that it hasn't been upvoted higher over all these concocted `SimpleDateFormats`. – David Moles May 07 '18 at 15:27
  • Glad I read more answers. I agree, this should be the answer now. – Xan-Kun Clark-Davis Jan 27 '20 at 16:01
  • And because it's `toString`, in many cases you won't even need to call it explicitly. – kaya3 Feb 25 '20 at 22:49
  • 1
    Warning in a comment on a previous answer applies here too: "Warning: The solution for Java 8 using ISO_INSTANT has an annoying quirk. When the milliseconds happen to be 0 they are not included in the output. This is allowed according to the ISO 8601 standard but many libraries and parsers in other languages are not that forgiving." – Dave L. Feb 26 '20 at 20:09
  • i would like to add that Date has a .toInstant() so something like: final Date expirationTime = new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME); expirationTime.toInstant().toString() //outputs "2022-02-21T17:19:54.667Z" – Paolo Feb 11 '22 at 17:20
  • Basil Bourque's answer is an improvement on this one in that it shows how to easily truncate the time to only include hours and minutes, which is what the OP asked for. – Gillfish Apr 28 '22 at 22:35
131

Java 8:

thisMoment = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mmX")
                              .withZone(ZoneOffset.UTC)
                              .format(Instant.now());

Pre Java 8:

thisMoment = String.format("%tFT%<tRZ",
                           Calendar.getInstance(TimeZone.getTimeZone("Z")));

From the docs:

'R'    Time formatted for the 24-hour clock as "%tH:%tM"
'F'    ISO 8601 complete date formatted as "%tY-%tm-%td".

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • @aioobe Again, string `"%tFT% – yegor256 Oct 12 '10 at 12:20
  • Just encapsulate it into a class then? Introducing dependencies for the sake of formatting todays date smells like bit rot to me. – aioobe Oct 12 '10 at 12:21
  • @aioobe And then I have to give an access to this class to all other classes that need date/time formatting? And from other packages? Looks like re-inventing joda (or something similar), don't you think so? – yegor256 Oct 12 '10 at 12:28
  • 26
    Well, either you include an extra third-party library as a dependency to your project (which you may want to keep up to date, and ship with your application, hey, it's just an extra 3.2 megabytes) and do `DateTime dt = new DateTime(); DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); String str = fmt.print(dt);`, or you do encapsulate `return String.format("%tFT% – aioobe Oct 12 '10 at 12:36
  • 11
  • 3
    A very neat solution, should be the accepted answer by now :) – AbdelHady Aug 21 '14 at 16:28
  • 4
    @PatrickLinskey has a helpful comment for adding the seconds and milliseconds to the output, but the pattern for milliseconds has a small error. The Z should appear after the milliseconds like this `%tFT% – sho222 Oct 03 '14 at 20:55
  • 1
    Just to mention that since Java 8 there is the `java.time` package available, and inspired in Joda-Time – Jaime Hablutzel Apr 17 '15 at 22:37
  • 2
    `DateTimeFormatter` has the constant `ISO_DATE_TIME` to get an ISO-8601 date formatter, instead of explicitly writing the pattern yourself. – nickb Jan 02 '17 at 20:45
31

use JodaTime

The ISO 8601 calendar system is the default implementation within Joda-Time

Here is the doc for JodaTime Formatter

Edit:

If you don't want to add or if you don't see value of adding above library you could just use in built SimpleDateFormat class to format the Date to required ISO format

as suggested by @Joachim Sauer

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());
jmj
  • 237,923
  • 42
  • 401
  • 438
  • 3
    And how would you produce a String formated as shown in the question? – Joachim Sauer Oct 12 '10 at 12:12
  • 4
    I'd say don't add a library-dependency for something as simple as this (which can be achieved with two lines of java-code). (Sure, if the requirements grows, it's another story.) – aioobe Oct 12 '10 at 12:14
  • 1
    @aioobe , if its just used in several part of app then its ok to go for default, in rest case jodatime is better. – jmj Oct 12 '10 at 12:15
  • 5
    @aioobe jodatime is better in any case, because it has `ISODateTimeFormat` -- a predefined formatter of ISO-8601. – yegor256 Oct 12 '10 at 12:19
  • 3
    @org.life.java: which are only relevant when you can switch to Jode time properly. You won't have them, when you use only this function of Joda time. – Joachim Sauer Oct 12 '10 at 13:29
  • Joda link is no longer valid unfortunately – fIwJlxSzApHEZIl Mar 09 '18 at 00:22
  • FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Apr 10 '18 at 20:29
22

DateFormatUtils from Apache commons-lang3 have useful constants, for example: DateFormatUtils.ISO_DATETIME_FORMAT

yegor256
  • 102,010
  • 123
  • 446
  • 597
  • 5
    More accurately, the current moment in UTC: `DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC"));` current moment in default time zone: `DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(new Date())`; @yegor256 thanks for mentioning `DateFormatUtils`, having on board apache commons-lang it's worth to use the date format. – babinik Sep 18 '13 at 13:40
19

If you don't want to include Jodatime (as nice as it is)

javax.xml.bind.DatatypeConverter.printDateTime(
    Calendar.getInstance(TimeZone.getTimeZone("UTC"))
);

which returns a string of:

2012-07-10T16:02:48.440Z

which is slightly different to the original request but is still ISO-8601.

Matthew Buckett
  • 4,073
  • 1
  • 36
  • 28
16

ISO 8601 may contains seconds see http://en.wikipedia.org/wiki/ISO_8601#Times

so the code should be

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
petertc
  • 3,607
  • 1
  • 31
  • 36
13

tl;dr

Some of the other Answers are correct in recommending java.time classes but go about using unnecessary lengths for your specific needs.

Instant.now()                               // Capture the current moment in UTC with a resolution as fines nanoseconds but usually in microseconds or milliseconds.
       .truncatedTo( ChronoUnit.MINUTES )   // Lop off any seconds or fractional second, to get a value in whole minutes.
       .toString()                          // Generate a String in standard ISO 8601 format where a `T` separates the year-month-day from the hour-minute-second, and the `Z` on the end for “Zulu” means UTC.

2018-01-23T12:34Z

Instant::toString

The jav.time.Instant class represents a moment in UTC, always in UTC.

Instant instant = Instant.now() ;

instant.toString(): 2018-01-23T12:34:56.123456Z

The Z on the end of your example string 2010-10-12T08:50Z is pronounced “Zulu” and means UTC.

Your desired format happens to comply with the ISO 8601 standard. The java.time classes use these standard formats by default when parsing/generating strings. So no need to specify a formatting pattern. Just call Instant::toString as seen above.

If you specifically want whole minutes without second or fractional second, then truncate. Specify a unit of time via ChronoUnit class.

Instant instant = Instant.now().truncatedTo( ChronoUnit.MINUTES ) ;
String output = instant.toString();  // Generate a `String` object in standard ISO 8601 format.

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?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
12

Joda-Time

Update: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. For Java 6 & 7, see the ThreeTen-Backport project, further adapted for Android in the ThreeTenABP project.

Using the Joda-Time library…

String output = new DateTime( DateTimeZone.UTC ).toString() ;

This is thread-safe. Joda-Time creates new immutable objects rather than changing existing objects.

If you truly intended to ask for a format without seconds, resolving to minutes, then use one of the many other built-in formatters in Joda-Time.

DateTime now = new DateTime( DateTimeZone.UTC ) ;
String output = ISODateTimeFormat.dateHourMinute.print( now ) ;

java.time

For Java 8 and later, Joda-Time continues to work. But the built-in java.time framework supplants Joda-Time. So migrate your code from Joda-Time to java.time as soon as is convenient.

See my other Answer for a modern solution.


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?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
7

For Java version 7

You can follow Oracle documentation: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X - is used for ISO 8601 time zone

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

System.out.println(nowAsISO);

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);

System.out.println(finalResult);
d.danailov
  • 9,594
  • 4
  • 51
  • 36
6

I do believe the easiest way is to first go to instant and then to string like:

String d = new Date().toInstant().toString();

Which will result in:

2017-09-08T12:56:45.331Z

Tuncay Göncüoğlu
  • 1,699
  • 17
  • 21
  • 4
    If you want the current time, there’s no need to go through an old-fashioned `Date` object. Just do `Instant.now().toString()`. If you got a `Date` from a legacy API, your method is the best one. – Ole V.V. Nov 15 '17 at 11:45
  • As Ole V.V. commented, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Apr 10 '18 at 20:29
5

You could use Java's SimpleDateFormat with the following pattern yyyy-MM-dd'T'HH:mm:ssXXX for ISO 8601.

Sample Code: (lists out for all the available time zones)

for (String timeZone : TimeZone.getAvailableIDs())
{
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    dateFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
    String formatted = dateFormat.format(new Date());
    System.out.print(formatted);

    if (formatted.endsWith("Z"))
    {
        // These time zone's have offset of '0' from GMT.
        System.out.print("\t(" + timeZone + ")");
    }

    System.out.println();
}

You could use:

TimeZone.getDefault()

for the default vm timezone. More here

You might notice the date time for few time zones that end with 'Z'. These time zones have offset of '0' from GMT.

More info can be found here.

always_a_rookie
  • 4,515
  • 1
  • 25
  • 46
3
private static String getCurrentDateIso()
{
    // Returns the current date with the same format as Javascript's new Date().toJSON(), ISO 8601
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    return dateFormat.format(new Date());
}
cprcrack
  • 17,118
  • 7
  • 88
  • 91
2

Here's a whole class optimized so that invoking "now()" doesn't do anything more that it has to do.

public class Iso8601Util
{
    private static TimeZone tz = TimeZone.getTimeZone("UTC");
    private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");

    static
    {
        df.setTimeZone(tz);
    }

    public static String now()
    {
        return df.format(new Date());
    }
}
gilbertpilz
  • 1,708
  • 20
  • 30
  • 9
    Making it static may cause trouble as SimpleDateFormat is not thread safe: "Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally." http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html – Juha Palomäki Feb 07 '13 at 21:10
  • 2
    As @Juha Palomäki mentioned, this is not threadsafe. If you are using Java 8 or higher, [ThreadLocal.withInitial](http://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html#withInitial-java.util.function.Supplier-) can fix that. If you are using Java 7 or lower, create a new ThreadLocal and supply an initial value by overriding [ThreadLocal.initialValue](http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html#initialValue()) – Matt Sgarlata Oct 16 '14 at 15:43
  • @user393274 - if you are using Java 8 you should use `Instant`, `DateTimeFormat` and the other modern thread safe replacements –  Sep 05 '17 at 18:08
  • I'm a bit puzzled by what the problem is with SimpleDateFormat not being thread safe. If two threads execute the static initializer at the same time, I can't see anything worse happening than the SimpleDateFormat constructor gets called twice but only one instant of it (the last one to finish) gets recorded as "df". – gilbertpilz Feb 07 '18 at 03:09
2
DateTimeFormatter.ISO_DATE_TIME
        .withZone(ZoneOffset.UTC)
        .format(yourDateObject.toInstant())
apen
  • 672
  • 4
  • 14
  • While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – Vishal Chhodwani Apr 27 '18 at 05:13
1

Still, joda-time does only support the extended format: "2015-12-09T00:22:42.930Z" not the basic: "20151209T002242.930Z" ...we might be better off testing a list of formats with java SimpleDateFormat.

1

I did it in Android using Calendar and SimpleDateFormat. The following method returns a Calendar with the "GMT" TimeZone (This is the universal time zone). Then you can use the Calendar class to set the hour between differents time zones, using the method setTimeZone() of the Calendar class.

private static final String GMT = "GMT";
private static final String DATE_FORMAT_ISO = "yyyyMMdd'T'HHmmss";

public static Calendar isoToCalendar(final String inputDate) {
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(GMT));
    try {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_ISO, Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone(GMT));
        Date date = dateFormat.parse(inputDate);
        calendar.setTime(date);
    } catch (ParseException e) {
        Log.e("TAG",e.getMessage());
    }
    return calendar;
}

REMEMBER: The Date class doesn't know about the TimeZone existence. By this reason, if you debug one date,you always see the date for your current timezone.

Gerardo Suarez
  • 352
  • 2
  • 13
1

They should have added some kind of simple way to go from Date to Instant and also a method called toISO8601, which is what a lot of people are looking for. As a complement to other answers, from a java.util.Date to ISO 8601 format:

Instant.ofEpochMilli(date.getTime()).toString();

It is not really visible when using auto-completion but: java.time.Instant.toString():

A string representation of this instant using ISO-8601

Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
1

If you care about performance, I created a library which outperforms standard Java parser and formatter in manipulating with ISO8601-formatted dates. DatetimeProcessor implementations are thread-safe and can be cached in a concurrent map or static fields.

<dependency>
  <groupId>com.axibase</groupId>
  <artifactId>date-processor</artifactId>
  <version>1.0.3</version>
</dependency>
import com.axibase.date.DatetimeProcessor;
import com.axibase.date.PatternResolver;
import org.junit.Before;
import org.junit.Test;

import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class DateFormatTest {
    private Clock clock;

    @Before
    public void prepare() {
        clock = Clock.fixed(Instant.ofEpochMilli(1571285405300L), ZoneId.of("Europe/Berlin"));
    }

    @Test
    public void testIsoMillis(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("iso");
        assertThat(formatter.print(clock.millis(), ZoneOffset.UTC), is("2019-10-17T04:10:05.300Z"));
    }

    @Test
    public void testIsoMillisLocalZone(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("iso");
        assertThat(formatter.print(clock.millis(), clock.getZone()), is("2019-10-17T06:10:05.300+02:00"));
    }

    @Test
    public void testIsoMinutes(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("yyyy-MM-ddTHH:mmXXX");
        assertThat(formatter.print(clock.millis(), ZoneOffset.UTC), is("2019-10-17T04:10Z"));
    }
}

0

Java 8+

If you are still using SimpleDateFormat with new Instant API, it will not work. Use DateTimeFormatter instead.

Instant ts = Instant.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000'Z'")
                .withZone(ZoneId.systemDefault());
String output = formatter.format(ts);
Sorter
  • 9,704
  • 6
  • 64
  • 74
-1

For those using Joda Time, here's a one-liner in the format yyyy-MM-dd'T'HH:mm:ss'Z'

DateTime(timeInMillis, DateTimeZone.UTC).toString(ISODateTimeFormat.dateTimeNoMillis())
Andrew Chelix
  • 1,012
  • 11
  • 16
-2

Try This,

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ");
        String date=sdf.format (new Date() );

Its For ISO 8601 format

Surej
  • 358
  • 1
  • 2
  • 16