首页 文章

将Java Date转换为UTC String

提问于
浏览
27

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

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

  • 在UTC中创建 java.util.Date 的字符串表示形式的最佳方法是什么?

  • 如何用更好的格式替换j.u.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"));

7 回答

  • 14

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

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

  • 6

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

    • 做空(单线)

    • 将一次性对象(时区,格式)表示为字符串

    • 从包装盒中支持有用的,可排序的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"
    

    代码

    (此代码也是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);
        }
    }
    
  • 1

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

  • 0

    java.time

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

    最好的解决方案是 sort your date-time objects rather than strings . 但如果您必须使用字符串,请继续阅读 .

    Instant表示时间轴上的一个时刻,基本上在UTC(有关详细信息,请参阅类doc) . toString实现默认使用DateTimeFormatter.ISO_INSTANT格式 . 这种格式包括零,三,六或九位数字,根据需要显示一秒的分数,最高达到nanosecond精度 .

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

    如果必须与旧的 Date 类进行互操作,则通过添加到旧类的新方法转换为/从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

    UPDATE: 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
    
  • 0

    java.time.Instant

    只需使用 java.timeInstant即可 .

    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 .

  • 25

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

    我希望这有助于某人 .

  • 2

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

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

相关问题