将 Java 日期转换为 UTC 字符串tl;博士java.time关于 java.time 城大时间

2022-09-01 00:34:10

java.util.Date 方法以本地时区显示日期。toString()

我们希望以 UTC 格式打印数据的几种常见方案,包括日志、数据导出和与外部程序的通信。

  • 在 UTC 中创建字符串表示形式的最佳方法是什么?java.util.Date
  • 如何用更好的格式替换j.u.Date的格式,这是不可排序的(谢谢,@JonSkeet!)?toString()

补遗

我认为以自定义格式和时区打印日期的标准方法非常繁琐:

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

答案 1

tl;博士

你问:

我正在寻找一个单行,如:

求你,你们必得领受。从可怕的遗留类转换为其现代替代品, .DateInstant

myJavaUtilDate.toInstant().toString()

2020-05-19T10:46:12.912Z

java.time

在Java 8及更高版本中,我们内置了新的java.time包教程)。灵感来自Joda-Time,由JSR 310定义,并由ThreeTen-Extra项目扩展。

最好的解决方案是对日期时间对象而不是字符串进行排序。但是,如果您必须在字符串中工作,请继续阅读。

即时表示时间轴上的一个时刻,基本上采用UTC格式(有关确切的详细信息,请参阅类文档)。默认情况下,toString 实现使用 DateTimeFormatter.ISO_INSTANT 格式。此格式根据需要包括零位、三位、六位或九位数字,以显示纳精度的分数。

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

如果必须与旧类进行互操作,请通过添加到旧类的新方法与 java.time 进行互操作。例:。DateDate::toInstant

myJavaUtilDate.toInstant().toString()

如果您需要小数秒的位数一致,或者不需要小数秒,则可能需要使用备用格式化程序。

如果要截断秒的小数,另一种方法是使用 而不是 调用其方法将分数更改为零ZonedDateTimeInstant

请注意,我们必须指定一个时区(因此名称)。在我们的例子中,这意味着UTC。ZoneID 的子类 ZoneOffset 持有 UTC 的方便常量。如果我们省略时区,则隐式应用 JVM 的当前默认时区ZonedDateTime

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


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。Hibernate 5 & JPA 2.2 支持 java.timejava.sql.*

从哪里获取 java.time 类?


城大时间

更新:Joda -Time项目现在处于维护模式,团队建议迁移到java.time类。

我正在寻找一个单线

如果使用Joda-Time 2.3库,则很容易。ISO 8601 是默认格式。

时区

在下面的代码示例中,请注意,我指定的是时区,而不是依赖于默认时区。在本例中,我根据您的问题指定 UTC。末尾的“祖鲁语”表示没有与 UTC 偏移的时区。Z

示例代码

// import org.joda.time.*;

String output = new DateTime( DateTimeZone.UTC );

输出。。。

2013-12-12T18:29:50.588Z

答案 2

在有用的注释之后,我完全重建了日期格式化程序。用法应该是:

  • 简短(一条衬垫)
  • 将一次性对象(时区、格式)表示为字符串
  • 支持有用的、可排序的 ISO 格式和盒装中的传统格式

如果你认为这段代码有用,我可能会在github中发布源代码和JAR。

用法

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