[java] Convert Java Date to UTC String

The java.util.Date toString() method displays the date in the local time zone.

There are several common scenarios where we want the data to be printed in UTC, including logs, data export and communication with external programs.

  • What's the best way to create a String representation of java.util.Date in UTC?
  • How to replace the j.u.Date’s toString() format, which isn't sortable (thanks, @JonSkeet!) with a better format?

Addendum

I think that the standard way of printing the date in a custom format and time zone is quite tedious:

final Date date = new Date();
final String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
final SimpleDateFormat sdf = new SimpleDateFormat(ISO_FORMAT);
final TimeZone utc = TimeZone.getTimeZone("UTC");
sdf.setTimeZone(utc);
System.out.println(sdf.format(date));

I was looking for a one-liner like:

System.out.println(prettyPrint(date, "yyyy-MM-dd'T'HH:mm:ss.SSS zzz", "UTC"));

This question is related to java datetime string-formatting utc

The answer is


Following the useful comments, I've completely rebuilt the date formatter. Usage is supposed to:

  • Be short (one liner)
  • Represent disposable objects (time zone, format) as Strings
  • Support useful, sortable ISO formats and the legacy format from the box

If you consider this code useful, I may publish the source and a JAR in github.

Usage

// The problem - not UTC
Date.toString()                      
"Tue Jul 03 14:54:24 IDT 2012"

// ISO format, now
PrettyDate.now()        
"2012-07-03T11:54:24.256 UTC"

// ISO format, specific date
PrettyDate.toString(new Date())         
"2012-07-03T11:54:24.256 UTC"

// Legacy format, specific date
PrettyDate.toLegacyString(new Date())   
"Tue Jul 03 11:54:24 UTC 2012"

// ISO, specific date and time zone
PrettyDate.toString(moonLandingDate, "yyyy-MM-dd hh:mm:ss zzz", "CST") 
"1969-07-20 03:17:40 CDT"

// Specific format and date
PrettyDate.toString(moonLandingDate, "yyyy-MM-dd")
"1969-07-20"

// ISO, specific date
PrettyDate.toString(moonLandingDate)
"1969-07-20T20:17:40.234 UTC"

// Legacy, specific date
PrettyDate.toLegacyString(moonLandingDate)
"Wed Jul 20 08:17:40 UTC 1969"

Code

(This code is also the subject of a question on Code Review stackexchange)

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * Formats dates to sortable UTC strings in compliance with ISO-8601.
 * 
 * @author Adam Matan <[email protected]>
 * @see http://stackoverflow.com/questions/11294307/convert-java-date-to-utc-string/11294308
 */
public class PrettyDate {
    public static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
    public static String LEGACY_FORMAT = "EEE MMM dd hh:mm:ss zzz yyyy";
    private static final TimeZone utc = TimeZone.getTimeZone("UTC");
    private static final SimpleDateFormat legacyFormatter = new SimpleDateFormat(LEGACY_FORMAT);
    private static final SimpleDateFormat isoFormatter = new SimpleDateFormat(ISO_FORMAT);
    static {
        legacyFormatter.setTimeZone(utc);
        isoFormatter.setTimeZone(utc);
    }

    /**
     * Formats the current time in a sortable ISO-8601 UTC format.
     * 
     * @return Current time in ISO-8601 format, e.g. :
     *         "2012-07-03T07:59:09.206 UTC"
     */
    public static String now() {
        return PrettyDate.toString(new Date());
    }

    /**
     * Formats a given date in a sortable ISO-8601 UTC format.
     * 
     * <pre>
     * <code>
     * final Calendar moonLandingCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
     * moonLandingCalendar.set(1969, 7, 20, 20, 18, 0);
     * final Date moonLandingDate = moonLandingCalendar.getTime();
     * System.out.println("UTCDate.toString moon:       " + PrettyDate.toString(moonLandingDate));
     * >>> UTCDate.toString moon:       1969-08-20T20:18:00.209 UTC
     * </code>
     * </pre>
     * 
     * @param date
     *            Valid Date object.
     * @return The given date in ISO-8601 format.
     * 
     */

    public static String toString(final Date date) {
        return isoFormatter.format(date);
    }

    /**
     * Formats a given date in the standard Java Date.toString(), using UTC
     * instead of locale time zone.
     * 
     * <pre>
     * <code>
     * System.out.println(UTCDate.toLegacyString(new Date()));
     * >>> "Tue Jul 03 07:33:57 UTC 2012"
     * </code>
     * </pre>
     * 
     * @param date
     *            Valid Date object.
     * @return The given date in Legacy Date.toString() format, e.g.
     *         "Tue Jul 03 09:34:17 IDT 2012"
     */
    public static String toLegacyString(final Date date) {
        return legacyFormatter.format(date);
    }

    /**
     * Formats a date in any given format at UTC.
     * 
     * <pre>
     * <code>
     * final Calendar moonLandingCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
     * moonLandingCalendar.set(1969, 7, 20, 20, 17, 40);
     * final Date moonLandingDate = moonLandingCalendar.getTime();
     * PrettyDate.toString(moonLandingDate, "yyyy-MM-dd")
     * >>> "1969-08-20"
     * </code>
     * </pre>
     * 
     * 
     * @param date
     *            Valid Date object.
     * @param format
     *            String representation of the format, e.g. "yyyy-MM-dd"
     * @return The given date formatted in the given format.
     */
    public static String toString(final Date date, final String format) {
        return toString(date, format, "UTC");
    }

    /**
     * Formats a date at any given format String, at any given Timezone String.
     * 
     * 
     * @param date
     *            Valid Date object
     * @param format
     *            String representation of the format, e.g. "yyyy-MM-dd HH:mm"
     * @param timezone
     *            String representation of the time zone, e.g. "CST"
     * @return The formatted date in the given time zone.
     */
    public static String toString(final Date date, final String format, final String timezone) {
        final TimeZone tz = TimeZone.getTimeZone(timezone);
        final SimpleDateFormat formatter = new SimpleDateFormat(format);
        formatter.setTimeZone(tz);
        return formatter.format(date);
    }
}

tl;dr

You asked:

I was looking for a one-liner like:

Ask and ye shall receive. Convert from terrible legacy class Date to its modern replacement, Instant.

myJavaUtilDate.toInstant().toString()

2020-05-05T19:46:12.912Z

java.time

In Java 8 and later we have the new java.time package built in (Tutorial). Inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project.

The best solution is to sort your date-time objects rather than strings. But if you must work in strings, read on.

An Instant represents a moment on the timeline, basically in UTC (see class doc for precise details). The toString implementation uses the DateTimeFormatter.ISO_INSTANT format by default. This format includes zero, three, six or nine digits digits as needed to display fraction of a second up to nanosecond precision.

String output = Instant.now().toString(); // Example: '2015-12-03T10:15:30.120Z'

If you must interoperate with the old Date class, convert to/from java.time via new methods added to the old classes. Example: Date::toInstant.

myJavaUtilDate.toInstant().toString()

You may want to use an alternate formatter if you need a consistent number of digits in the fractional second or if you need no fractional second.

Another route if you want to truncate fractions of a second is to use ZonedDateTime instead of Instant, calling its method to change the fraction to zero.

Note that we must specify a time zone for ZonedDateTime (thus the name). In our case that means UTC. The subclass of ZoneID, ZoneOffset, holds a convenient constant for UTC. If we omit the time zone, the JVM’s current default time zone is implicitly applied.

String output = ZonedDateTime.now( ZoneOffset.UTC ).withNano( 0 ).toString();  // Example: 2015-08-27T19:28:58Z

Table of date-time types in Java, both modern and legacy


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.

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

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

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. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?


Joda-Time

UPDATE: The Joda -Time project is now in maintenance mode, with the team advising migration to the java.time classes.

I was looking for a one-liner

Easy if using the Joda-Time 2.3 library. ISO 8601 is the default formatting.

Time Zone

In the code example below, note that I am specifying a time zone rather than depending on the default time zone. In this case, I'm specifying UTC per your question. The Z on the end, spoken as "Zulu", means no time zone offset from UTC.

Example Code

// import org.joda.time.*;

String output = new DateTime( DateTimeZone.UTC );

Output…

2013-12-12T18:29:50.588Z

The following simplified code, based on the accepted answer above, worked for me:

public class GetSync {
    public static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
    private static final TimeZone utc = TimeZone.getTimeZone("UTC");
    private static final SimpleDateFormat isoFormatter = new SimpleDateFormat(ISO_FORMAT);
    static {
        isoFormatter.setTimeZone(utc);
    }

    public static String now() {
        return isoFormatter.format(new Date()).toString();
    }
}

I hope this helps somebody.


Well if you want to use java.util.Date only, here is a small trick you can use:

String dateString = Long.toString(Date.UTC(date.getYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));


If XStream is a dependency, try:

new com.thoughtworks.xstream.converters.basic.DateConverter().toString(date)

java.time.Instant

Just use Instant of java.time.

    System.out.println(Instant.now());

This just printed:

2018-01-27T09:35:23.179612Z

Instant.toString always gives UTC time.

The output is usually sortable, but there are unfortunate exceptions. toString gives you enough groups of three decimals to render the precision it holds. On the Java 9 on my Mac the precision of Instant.now() seems to be microseconds, but we should expect that in approximately one case out of a thousand it will hit a whole number of milliseconds and print only three decimals. Strings with unequal numbers of decimals will be sorted in the wrong order (unless you write a custom comparator to take this into account).

Instant is one of the classes in java.time, the modern Java date and time API, which I warmly recommend that you use instead of the outdated Date class. java.time is built into Java 8 and later and has also been backported to Java 6 and 7.


Why not just use java.text.SimpleDateFormat ?

Date someDate = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String s = df.format(someDate);

Or see: http://www.tutorialspoint.com/java/java_date_time.htm


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to datetime

Comparing two joda DateTime instances How to format DateTime in Flutter , How to get current time in flutter? How do I convert 2018-04-10T04:00:00.000Z string to DateTime? How to get current local date and time in Kotlin Converting unix time into date-time via excel Convert python datetime to timestamp in milliseconds SQL Server date format yyyymmdd Laravel Carbon subtract days from current date Check if date is a valid one Why is ZoneOffset.UTC != ZoneId.of("UTC")?

Examples related to string-formatting

JavaScript Chart.js - Custom data formatting to display on tooltip Format in kotlin string templates Converting Float to Dollars and Cents Chart.js - Formatting Y axis String.Format not work in TypeScript Use StringFormat to add a string to a WPF XAML binding How to format number of decimal places in wpf using style/template? How to left align a fixed width string? Convert Java Date to UTC String Format a Go string without printing?

Examples related to utc

Convert LocalDateTime to LocalDateTime in UTC How to set the timezone in Django? Java Convert GMT/UTC to Local time doesn't work as expected Should MySQL have its timezone set to UTC? How to Convert UTC Date To Local time Zone in MySql Select Query How to convert UTC timestamp to device local time in android Convert python datetime to epoch with strftime Convert Java Date to UTC String How do I get a UTC Timestamp in JavaScript? Converting datetime.date to UTC timestamp in Python