【问题标题】:How to convert UTC time format to Date in Java如何在 Java 中将 UTC 时间格式转换为日期
【发布时间】:2021-08-19 19:30:20
【问题描述】:

我必须调用一个需要日期字段的 Web 服务,但他们希望它采用以下格式 YYYY-MM-DDThh:mm:ss.sssZ。我该怎么做?

我尝试了以下

OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);

Date.from(transactionTime.toInstant());

但这没有用。 transactionTime 是 2021-06-01T15:11:09.942843400Z,但 Date.from 将其转换为 Tue Jun 01 11:11:09 EDT 2021。

顺便说一句,我使用的是 Java 11

【问题讨论】:

  • 2021-06-01T15:11:09.942843400Z(祖鲁,格林威治时间) 2021-06-01T11:11:09.942843400 EDT。在不同时区是同一时刻。
  • "Date.from 将其转换为 Tue Jun 01 11:11:09 EDT 2021" - 不,Date.from 将其转换为 Date 对象,它不是字符串。如果您需要以特定方式格式化 Date 对象,有多种方法(例如 SimpleDateFormat)。
  • java.util.Date 没有时区的概念。字符串 Tue Jun 01 11:11:09 EDT 2021 代表您所在时区的日期时间。由于Date 没有时区信息,它应用JVM 的时区来返回Date#toString 的值。
  • A Date 也不能有格式。
  • 是什么让您认为您想要Date?该类设计不佳且已过时,并且 Web 服务不直接使用 Date 对象,因此您不应该想要一个。最好坚持你的OffsetDateTime

标签: java date utc


【解决方案1】:
Instant.now().toString()

查看代码run live at IdeOne.com

2021-06-01T15:21:16.783779Z

该格式在ISO 8601 标准中定义。结尾的Z 表示与UTC 的偏移量为零时分秒。发音为“祖鲁语”。

使用java.time.Instant 表示以UTC 表示的时刻。

另一个方向,从文本到对象。

Instant.parse( "2021-06-01T15:21:16.783779Z" ) 

如果您只想要毫秒,您可以通过truncating 去掉任何微秒和纳秒。

Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;

永远不要使用旧的 Date 类。仅使用 java.time 类。

【讨论】:

    【解决方案2】:

    使用DateTimeFormatter 格式化日期时间对象

    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
    import java.time.format.DateTimeFormatter;
    
    public class Main {
        public static void main(String[] args) {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
            OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
            String formatted = transactionTime.format(dtf);
            System.out.println(formatted);
        }
    }
    

    输出:

    2021-06-01T15:49:45.198Z
    

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    如果我想使用java.util.Date怎么办?

    出于任何原因,如果您需要将OffsetDateTime 的对象转换为java.util.Date 的对象,您可以这样做:

    Date date = Date.from(transactionTime.toInstant());
    

    注意java.util.Date 对象不是像modern Date-Time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即January 1, 1970, 00:00:00 GMT(或 UTC)。由于Date 没有时区信息,它应用JVM 的时区以EEE MMM dd HH:mm:ss z yyyy 的格式返回Date#toString 的值,该格式是从这个毫秒值计算出来的。如果您需要以不同的格式和时区打印日期时间,则需要使用具有所需格式的 SimpleDateFormat 并将时区设置为适用的格式,例如

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
    sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
    String strDate = sdf.format(date);
    System.out.println(strDate);
    

    输出:

    2021-06-01T15:49:45.198Z
    

    其他一些重要说明:

    1. java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*
    2. 您在YYYY-MM-DDThh:mm:ss.sssZ 中使用的大多数符号都是错误的。查看DateTimeFormatterSimpleDateFormat 的文档页面中的符号说明。

    * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport 将大部分 java.time 功能反向移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 2021-10-14
      • 2013-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多