Преобразование даты Java в строку UTC

на java.утиль.Дата toString() метод отображает дату в местном часовом поясе.

существует несколько распространенных сценариев, в которых мы хотим, чтобы данные были напечатаны в UTC, включая журналы, экспорт данных и связь с внешними программами.

  • каков наилучший способ создания строкового представления java.util.Date в UTC?
  • как заменить j.u.Дата toString() формат, который не сортируется (спасибо, @JonSkeet!) с лучшим форматом?

дополнительное соглашение

Я думаю, что стандартный способ печати даты в пользовательском формате и часовом поясе довольно утомительно:

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));

Я искал один-лайнер, как:

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

7 ответов


java.время

в Java 8 и позже у нас есть новый java.пакет времени построен в (учебник). Вдохновленный Joda-Time, определенный JSR 310 и расширенный ThreeTen-Extra.

лучшее решение -сортировать объекты даты и времени, а не строки. Но если вы должны работать в строках, читайте дальше.

An Instant представляет момент на временной шкале, в основном в UTC (см. class doc для точных деталей). The toString реализация использует DateTimeFormatter.ISO_INSTANT формат по умолчанию. Этот формат включает ноль, три, шесть или девять цифр цифр, необходимых для отображения доли секунды до НС точности.

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

если вы должны взаимодействовать со старых Date класс, преобразовать в / из java.время с помощью новых методов, добавленных к старым классам. Образец: Date::toInstant.

myJavaUtilDate.toInstant().toString()

вы можете использовать альтернативный форматер, если вам нужно согласованное количество цифр в дробной секунде или если вам не нужна дробная секунда.

другой маршрут, если вы хотите усечь доли секунды, это использовать ZonedDateTime вместо Instant, назвав его метод изменения дроби на ноль.

обратите внимание, что мы должны указать часовой пояс ZonedDateTime (отсюда и название). В нашем случае это означает UTC. Этот подкласс ZoneID, ZoneOffset, имеет удобный константа для UTC. Если мы опустим часовой пояс, JVM текущий часовой пояс неявно применяется.

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

Joda Времени

обновление: проект Joda-Time теперь находится в режиме обслуживания, с командой, консультирующей миграцию на java.классы время.

я искал одну строчку

легко при использовании Joda Времени 2.3 библиотека. ISO 8601 форматирование по умолчанию.

Часовой Пояс

в приведенном ниже примере кода обратите внимание, что я указываю часовой пояс, а не в зависимости от часового пояса по умолчанию. В этом случае я указываю UTC на ваш вопрос. The Z в конце, говорят как "Зулу", означает отсутствие смещения часового пояса от UTC.

пример Код

// import org.joda.time.*;

String output = new DateTime( DateTimeZone.UTC );

выход...

2013-12-12T18:29:50.588Z

следуя полезным комментариям, я полностью перестроил форматер даты. Использование должно:

  • быть коротким (один вкладыш)
  • представлять одноразовые объекты (часовой пояс, формат) в виде строк
  • поддержка полезных, сортируемых форматов ISO и устаревшего формата из коробки

Если вы считаете этот код полезным, я могу опубликовать источник и банку в на GitHub.

использование

// 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"

код

(этот код также является предметом вопрос по обзору кода 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 <adam@matan.name>
 * @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);
    }
}

следующий упрощенный код, основанный на принятый ответ выше, работал на меня:

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();
    }
}

надеюсь, это кому-то поможет.


java.время.Instant

просто использовать Instant of java.time.

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

это только что напечатано:

2018-01-27T09:35:23.179612Z

Instant.toString всегда дает время UTC.

выход обычно сортируется, но есть неудачные исключения. toString дает вам достаточно групп из трех десятичных знаков, чтобы отобразить точность, которую он держит. На Java 9 на моем Mac точность Instant.now() кажется, микросекунды, но мы должны ожидать что примерно в одном случае из тысячи он попадет в целое число миллисекунд и напечатает только три десятичных знака. Строки с неравным числом десятичных знаков будут отсортированы в неправильном порядке (если вы не напишете пользовательский компаратор для учета этого).

Instant один из классов в java.time, современный API даты и времени Java, который я настоятельно рекомендую использовать вместо устаревшего Date класса. java.time встроен в Java 8 и позже, а также был backported на Java 6 и 7.


Если XStream является зависимостью, попробуйте:

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

почему бы просто не использовать Java.текст.Класса simpledateformat ?

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

или увидеть: http://www.tutorialspoint.com/java/java_date_time.htm


Ну, если вы хотите использовать Java.утиль.Только дата, вот небольшой трюк, который вы можете использовать:

строка dateString = Long.метод toString(дата.UTC(дата.getYear (), дата.getMonth(), дата.getDate (), дата.getHours(), дата.getMinutes(), дата.getSeconds()));