将Java Date转换为UTC String

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

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

  • 在UTC中创建java.util.Date的String表示forms的最佳方法是什么?
  • 如何用更好的格式替换juDate的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")); 

java.time

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

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

Instant表示时间轴上的一个时刻,基本上是UTC (有关详细信息,请参阅类doc)。 toString实现默认使用DateTimeFormatter.ISO_INSTANT格式。 该格式包括所需的零,三,六或九位数字,以显示一秒至纳秒精度的分数。

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

如果必须与旧的Date类进行互操作,则通过添加到旧类的新方法转换为/来自java.time。 示例: 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 -Time项目现在处于维护模式,团队建议迁移到java.time类。

我正在寻找一个单行

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

时区

在下面的代码示例中,请注意我指定的是时区而不是默认时区。 在这种情况下,我根据您的问题指定UTC 。 最后的Z ,称为“Zulu”,意味着没有时区偏离UTC。

示例代码

 // import org.joda.time.*; String output = new DateTime( DateTimeZone.UTC ); 

输出…

 2013-12-12T18:29:50.588Z 

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

  • 短(一个class轮)
  • 将一次性对象(时区,格式)表示为字符串
  • 从包装盒中支持有用的,可排序的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  * @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, eg : * "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. * * 
 *  * 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 *  * 

* * @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. * *

 *  * System.out.println(UTCDate.toLegacyString(new Date())); * >>> "Tue Jul 03 07:33:57 UTC 2012" *  * 

* * @param date * Valid Date object. * @return The given date in Legacy Date.toString() format, eg * "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. * *

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

* * * @param date * Valid Date object. * @param format * String representation of the format, eg "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, eg "yyyy-MM-dd HH:mm" * @param timezone * String representation of the time zone, eg "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.time.Instant

只需使用java.time Instant java.time

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

这只是打印:

 2018-01-27T09:35:23.179612Z 

Instant.toString始终给出UTC时间。

输出通常是可排序的,但有一些不幸的例外。 toString为您提供足够的三位小数组,以呈现它所保持的精度。 在我的Mac上的Java 9上, Instant.now()的精度似乎是微秒,但我们应该预计,在大约一个例子中,它将达到整数毫秒并且只打印三个小数。 具有不等小数位数的字符串将按错误的顺序排序(除非您编写自定义比较器以将其考虑在内)。

Instantjava.time一个类,即现代Java日期和时间API,我强烈建议您使用而不是过时的Date类。 java.time内置于Java 8及更高版本中,并且已经向后移植到Java 6和7。

如果XStream是依赖项,请尝试:

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

为什么不使用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

好吧,如果你只想使用java.util.Date,这里有一个小技巧你可以使用:

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