【问题标题】:SimpleDateFormat results in incorrect timeSimpleDateFormat 导致时间不正确
【发布时间】:2017-05-23 09:47:58
【问题描述】:

我有以下代码

    protected void amethod1() {
    String strDate = "Thu May 18 16:24:59 UTC 2017";
    String dateFormatStr = "EEE MMM dd HH:mm:ss zzz yyyy";
    DateFormat dateFormat = new SimpleDateFormat(dateFormatStr);

    Date formattedDate = null;
    try {
        formattedDate = dateFormat.parse(strDate);
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

formattedDate 的结果值为 - "Thu May 18 11:24:59 CDT 2017" 。

我正在芝加哥测试这段代码,当地时区是 CDT。
我无法理解为什么时间值会从 16:24:59 变为 11:24:59。我是否遗漏了定义的日期格式的内容?

【问题讨论】:

  • 您将日期声明为 UTC,并在 CDT 中获得结果,因此差异是合乎逻辑的。您是否尝试在 UTC 中获得结果?
  • @Nathan - 是的,没错。我希望结果是 UTC。
  • java.util.Date 将时间转换为系统的时区。要获得 UTC,您可以将日期转换为 ZonedDateTime
  • 你应该先set your date timezone

标签: java simpledateformat date-format


【解决方案1】:

Date 类根本不包含任何时区。自格林威治标准时间 01.01.1970 00:00:00 以来,这只是几毫秒。如果您尝试使用System.out.println 或调试器查看formattedDate 包含的内容,您将获得本地时区的格式化日期。 11:24:59 CDT16:24:59 UTC是同一时间,所以结果是正确的。

Is java.util.Date using TimeZone?

最好使用jodatimeJava 8 Time API 以便更好地管理时间和时区。

【讨论】:

  • A Date 对象包含自 01-01-1970, 00:00:00 GMT 以来的 毫秒 数(不是秒,这是 Unix 时间)。跨度>
  • The JodaTime homepage 说“现在要求用户迁移到 java.time (JSR-310)。”所以最推荐使用 Java 8 日期和时间 API。
【解决方案2】:

首先,您得到了正确的时间。当芝加哥​​使用夏令时(5 月 18 日)时,UTC 时间是 16:24:59,时间是 11:24:59。因此,您的 Date 值代表同一时间点。这就是您对Date 的所有期望。

我了解您不仅需要时间点,还需要 UTC 时区。由于Axel P has already recommended Java 8 date and time API,我只是想填写详细信息:

    DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern(dateFormatStr, Locale.US);
    ZonedDateTime dateTime = ZonedDateTime.parse(strDate, parseFormatter);

结果是

2017-05-18T16:24:59Z[UTC]

如果你总是想要 UTC 时区,Instant 类正好适合它,所以你可能想要转换成它:

    Instant instant = dateTime.toInstant();

通俗地说,时刻始终采用 UTC。

【讨论】:

    【解决方案3】:

    SimpleDateFormat myFmt=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date now=new Date(); System.out.println(myFmt.format(now)); 希望能帮到你。如果可以,请采纳。谢谢

    【讨论】:

      【解决方案4】:

      formattedDate 的结果值为- "Thu May 18 11:24:59 CDT 2017" 。 为什么? 因为您的时区从 UTC 时间开始运行 -5 小时,您可以在下面的链接 wiki 时区缩写中找到,如果您想要获得相同时区的结果,您需要在格式化程序中指定时区 希望您得到我的关注

      https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations

      public static void amethod1() {
              String strDate = "Thu May 18 16:24:59 UTC 2017";
              String dateFormatStr = "EEE MMM dd HH:mm:ss zzz yyyy";
              SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
              dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
      
              Date formattedDate = null;
              try {
                  formattedDate = dateFormat.parse(strDate);
              } catch (ParseException e) {
                  e.printStackTrace();
              }
      
              System.out.println("formattedDate: "+dateFormat.format(formattedDate));
      
          }
      

      【讨论】:

        【解决方案5】:

        您指定了时区,这就是为什么在解析当前时区(您所在的位置)的时间后,SimpleDateFormat 会设置 UTC 时区。当您尝试输出您的日期时,它会显示在您当前的时区

        【讨论】:

          【解决方案6】:

          在格式化日期时,您似乎还需要指定时区,例如。 .TimeZone.setDefault(TimeZone.getTimeZone("PST")); 看看这个讨论TimeZone

          【讨论】:

            【解决方案7】:

            日期的输出取决于指定的格式,您可以在其中指定时区,如下例所示:

            protected void amethod2() {
                String strDate = "Thu May 18 16:24:59 UTC 2017";
                String dateFormatStr = "EEE MMM dd HH:mm:ss zzz yyyy";
                DateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
            
                Date formattedDate = null;
                try {
                    formattedDate = dateFormat.parse(strDate);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                System.out.println("Date: " + formattedDate);
                // Thu May 18 17:24:59 BST 2017, BST is my system default timezone
            
                // Set the time zone to UTC for the calendar of dateFormat
                dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                System.out.println("Date in timezone UTC: " + dateFormat.format(formattedDate));
                // Thu May 18 16:24:59 UTC 2017
            
                // Set the time zone to America/Chicago
                dateFormat.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
                System.out.println("Date in timezone America/Chicago: " + dateFormat.format(formattedDate));
                // Thu May 18 11:24:59 CDT 2017
            }
            

            对于示例中的“UTC”和“America/Chicago”等ID,您可以通过TimeZone.getAvailableIDs()获取它们的完整列表。你可以打印出来看看:

            Arrays.stream(java.util.TimeZone.getAvailableIDs()).forEach(System.out::println);

            你将拥有:

            Africa/Abidjan
            Africa/Accra
            Africa/Addis_Ababa
            Africa/Algiers
            Africa/Asmara
            Africa/Asmera
            Africa/Bamako
            Africa/Bangui
            Africa/Banjul
            Africa/Bissau
            Africa/Blantyre
            ...
            

            【讨论】:

              猜你喜欢
              • 2018-10-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多