Подтвердить что ты не робот

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

Метод java.util.Date toString() отображает дату в локальном часовом поясе.

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

  • Какой лучший способ создать строковое представление java.util.Date в UTC?
  • Как заменить формат j.u.Dates 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"));
4b9b3361

Ответ 1

После полезных комментариев, я полностью перестроил формат даты. Предполагается использование:

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

Если вы считаете этот код полезным, я могу опубликовать источник и JAR в 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"

Код

(Этот код также является предметом вопроса об обзоре кода Reviewexchange)

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

Ответ 2

Joda времени

Я искал однострочный

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

Часовой пояс

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

Пример кода

// import org.joda.time.*;

String output = new DateTime( DateTimeZone.UTC );

Вывод...

2013-12-12T18:29:50.588Z

java.time

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

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

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

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

Другой маршрут, если вы хотите усечь доли секунды, - это использовать ZonedDateTime вместо Instant, вызывая метод ZoneID, ZoneOffset, содержит удобная константа для UTC. Если мы опускаем часовой пояс, неявно применяется JVM текущий часовой пояс по умолчанию.

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

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

Почему бы просто не использовать java.text.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

Ответ 6

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

Строка dateString = Long.toString(Date.UTC(date.getYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()) );