java.util.Date toString()
方法在本地时区显示日期。
有几种常见情况我们希望在UTC中打印数据,包括日志,数据导出和与外部程序的通信。
java.util.Date
的字符串表示形式的最佳方法是什么?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"));
答案 0 :(得分:27)
在Java 8及更高版本中,我们内置了新的java.time package(Tutorial)。灵感来自Joda-Time,由JSR 310定义,并由ThreeTen-Extra项目扩展。
最佳解决方案是对日期时间对象进行排序,而不是字符串。但如果你必须使用字符串,请继续阅读。
Instant
表示时间轴上的一个时刻,基本上在UTC中(有关详细信息,请参阅类doc)。 toString
实现默认使用DateTimeFormatter.ISO_INSTANT
格式。此格式根据需要包括零,三,六或九位数字,以显示精确到nanosecond精度的秒数。
String output = Instant.now().toString(); // Example: '2015-12-03T10:15:30.120Z'
如果必须与旧的Date
类进行互操作,则通过添加到旧类的新方法转换为java.time或从java.time转换。示例:Date::toInstant
。
myJavaUtilDate.toInstant().toString()
如果您需要在小数秒内保持一致的位数,或者您不需要小数秒,则可能需要使用备用格式化程序。
如果要截断一秒的分数,另一条路线是使用ZonedDateTime
代替Instant
,调用其method to change the fraction to zero。
请注意,我们必须为ZonedDateTime
指定一个时区(因此名称)。在我们的情况下,这意味着UTC。 ZoneID
的子类ZoneOffset
拥有方便的constant for UTC。如果我们省略时区,则隐式应用JVM的current default time zone。
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
答案 1 :(得分:14)
根据有用的评论,我完全重建了日期格式化程序。用法应该是:
如果您认为此代码有用,我可以在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"
(此代码也是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 <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);
}
}
答案 2 :(得分:6)
基于the accepted answer above的以下简化代码对我有用:
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();
}
}
我希望这有助于某人。
答案 3 :(得分:2)
只需使用java.time
的{{3}}。
System.out.println(Instant.now());
刚刚打印出来:
2018-01-27T09:35:23.179612Z
Instant.toString
总是给出UTC时间。
输出通常可排序,但有一些不幸的例外情况。 toString
为您提供足够的三位小数组,以呈现它所保持的精度。在Mac上的Java 9上,Instant.now()
的精度似乎是微秒,但我们应该预计,在大约一个例子中,它将达到整数毫秒并且只打印三个小数。具有不等小数位数的字符串将按错误的顺序排序(除非您编写自定义比较器以将其考虑在内)。
Instant
是java.time
中的一个类,即现代Java日期和时间API,我强烈建议您使用而不是过时的Date
类。 java.time
内置于Java 8及更高版本中,并且已经向后移植到Java 6和7。
答案 4 :(得分:1)
如果XStream是依赖项,请尝试:
new com.thoughtworks.xstream.converters.basic.DateConverter().toString(date)
答案 5 :(得分:0)
为什么不使用java.text.SimpleDateFormat?
Date someDate = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String s = df.format(someDate);
答案 6 :(得分:0)
如果您只想使用java.util.Date,这里有一个小技巧:
String dateString = Long.toString(Date.UTC(date.getYear(),date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds()) );