【问题标题】:Calendar.getTime() not returning UTC date if TimeZone is defined如果定义了 TimeZone,Calendar.getTime() 不返回 UTC 日期
【发布时间】:2025-12-18 15:05:02
【问题描述】:

我已为我的日历实例执行此操作,以在 UTC 时区返回日期:

SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:SS Z");
TimeZone tz = TimeZoneUtil.getTimeZone(StringPool.UTC);
formatter.setTimeZone(tz);

    Date dtStart = null;
    Date dtEnd = null;

    try{
        dtStart = formatter.parse(formatter.format(startDate.getTime()));
        dtEnd = formatter.parse(formatter.format(endDate.getTime()));
    }catch (Exception e) {
        e.getStackTrace();
}

在我格式化日历时间戳以返回具有所需时区的字符串日期之前,它工作正常,但是当我将该字符串日期解析为日期日期时,它再次选择本地时区? 我需要将 Date 对象存储在 UTC 时区中。

任何帮助将不胜感激!

【问题讨论】:

标签: java datetime calendar timezone


【解决方案1】:

你可以用这个:

 Date localTime = new Date(); 

 //creating DateFormat for converting time from local timezone to GMT
 DateFormat converter = new SimpleDateFormat("dd/MM/yyyy:HH:mm:ss");

 //getting GMT timezone, you can get any timezone e.g. UTC
 converter.setTimeZone(TimeZone.getTimeZone("GMT"));

 System.out.println("local time : " + localTime);;
 System.out.println("time in GMT : " + converter.format(localTime));

它会给出:
当地时间:2013 年 6 月 21 日星期五 11:55:00 UTC
格林威治标准时间:21/06/2013:11:55:00

我希望它会有所帮助。

干杯。

【讨论】:

    【解决方案2】:

    Java 中的日期对象将始终将值存储在主机(您的系统)时区信息中。

    这是来自 javadoc:

    虽然 Date 类旨在反映协调世界时 (UTC),但它可能并不完全如此,这取决于 Java 虚拟机的主机环境。

    您应该尝试使用高级得多的Joda Time

    【讨论】:

    • 这不正确,默认的 Date() 构造函数存储了 System.currentTimeMillis() 的值,这是自 1970 年 1 月 1 日 UTC 以来的毫秒数。正如您提到的,“计算机时间”和 UTC 之间存在细微差异,请参阅leap seconds 上的讨论。但是 Joda Time 在这方面并没有提供任何优势,请参阅Are leap seconds supported
    【解决方案3】:

    与其在多个地方设置 TimeZone,不如使用 -Duser.timezone=GMT 或 PST 设置时区。

    而且,您可以通过一个实际示例轻松测试 Java 如何处理时区和 getTime() 忽略时区:

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // print with timezone
    
    
            TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("GMT"));
            TimeZone.setDefault(timeZone);          // set system timezone as GMT
            sdf.setTimeZone(timeZone);              // formatter also has a timezone
            Date date = new Date();
            System.out.println(date);               // system says GMT date
            System.out.println(date.getTime());     // only prints time in milliseconds after January 1, 1970 00:00:00 GMT
            System.out.println(sdf.format(date));
    
            timeZone = TimeZone.getTimeZone(ZoneId.of("America/Los_Angeles"));
            TimeZone.setDefault(timeZone);          // set system timezone as GMT
            sdf.setTimeZone(timeZone);              // formatter also has a timezone
            date = new Date();
            System.out.println(date);
            System.out.println(date.getTime());     // prints the same value as above, "not including timezone offset"
            System.out.println(sdf.format(date));
    
            // GMT and PDT times are same as getTime() only returns time in ms since UTC for the day ignoring timezone which is mostly used for formatting
    
    Wed Mar 14 22:43:43 GMT 2018
    1521067423108
    2018-03-14T22:43:43+0000
    
    Wed Mar 14 15:43:43 PDT 2018
    1521067423125                  // not includes timezone in getTime()
    2018-03-14T15:43:43-0700       // formatting looks fine
    

    【讨论】:

      【解决方案4】:

      很好地解释了为什么 Date 对象采用当前时区值,

      请参考SO answer

      编辑。


      在这里,我将添加答案的一些重要部分。


      java.util.Date 没有特定的时区,尽管它的值通常被认为与 UTC 相关。是什么让您认为是当地时间?

      准确地说:java.util.Date 中的值是自 Unix 纪元以来的毫秒数,该纪元发生在 UTC 时间 1970 年 1 月 1 日午夜。相同的纪元也可以在其他时区进行描述,但传统的描述是用 UTC 来描述的。由于自固定纪元以来的毫秒数,java.util.Date 中的值在任何特定时刻在世界各地都是相同的,无论本地时区如何。

      【讨论】: