【问题标题】:How do I display a date with a custom timezone?如何显示具有自定义时区的日期?
【发布时间】:2010-11-13 01:58:47
【问题描述】:

假设我有一个表示日期的字符串,如下所示:

“2009 年 7 月 8 日星期三 17:08:48 GMT”

所以我将该字符串解析为这样的日期对象:

DateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy");
Date fromDate = (Date)formatter.parse(fromDateString);

这给了我正确的日期对象。现在我想将此日期显示为 CDT 值。

我尝试了很多东西,但我无法让它正常工作。必须有一个使用 DateFormat 类的简单方法才能使其工作。有什么建议吗?我最后一次尝试是这样的:

formatter.setTimeZone(toTimeZone);
String result = formatter.format(fromDate);

【问题讨论】:

    标签: java date timezone date-format


    【解决方案1】:

    现代方法是使用 java.time 类。

    ZonedDateTime

    指定格式模式以匹配您的输入字符串。代码类似于SimpleDateFormat,但不完全一样。请务必阅读DateTimeFormatter 的课程文档。请注意,我们指定 Locale 来确定使用什么人类语言来表示星期几和月份的名称。

    String input = "Wed Jul 08 17:08:48 GMT 2009";
    DateTimeFormatter f = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss z uuuu" , Locale.ENGLISH );
    ZonedDateTime zdt = ZonedDateTime.parse ( input , f );
    

    zdt.toString(): 2009-07-08T17:08:48Z[GMT]

    我们可以将其调整到任何其他时区。

    continent/region 的格式指定proper time zone name。切勿使用 3-4 个字母的缩写,例如 CDTESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

    我猜CDT 是指像America/Chicago 这样的时区。

    ZoneId z = ZoneId.of( "America/Chicago" );
    ZonedDateTime zdtChicago = zdt.withZoneSameInstant( z );
    

    zdtChicago.toString() 2009-07-08T12:08:48-05:00[美国/芝加哥]

    Instant

    通常最好在 UTC 工作。为此提取InstantInstant 类代表UTC 中时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。

    Instant 类是 java.time 的基本构建块类。您可以将ZonedDateTime 视为Instant 加上ZoneId

    Instant instant = zdtChicago.toInstant();
    

    instant.toString(): 2009-07-08T17:08:48Z


    关于java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormat

    Joda-Time 项目现在位于maintenance mode,建议迁移到 java.time。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      【解决方案2】:

      很抱歉挖出一个旧线程。但我想知道是否有一个 java-class 将所有 time-zone-ids 保存为一个常量类。 因此,不必在像这样设置时区时对时区 ID 进行硬编码:

      formatter.setTimeZone(TimeZone.getTimeZone("US/Central"));
      

      我们会做一些更标准/更统一的事情:

      formatter.setTimeZone(TimeZone.getTimeZone(SomeConstantClass.US_CENTRAL)); 
      

      其中 SomeConstantClass.java 是一个类,其中包含引用 TimeZone 类支持的不同时区 ID 的常量。

      【讨论】:

        【解决方案3】:

        使用:

        formatter.setTimeZone(TimeZone.getTimeZone("US/Central"));
        

        输出:

        Wed Jul 08 12:08:48 CDT 2009
        

        在我的机器上你的例子中的日期。那是在格式字符串中用 zzz 代替 ZZZ 之后。

        【讨论】:

          【解决方案4】:

          使用“zzz”而不是“ZZZ”:“Z”是 RFC822 时区的符号。

          DateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
          

          话虽如此,我对日期/时间的标准建议是使用Joda Time,这是一个更好的 API。

          编辑:简短但完整的程序:

          import java.text.*;
          import java.util.*;
          
          public class Test
          {
              public List<String> names;
          
              public static void main(String [] args)
                  throws Exception // Just for simplicity!
              {
                  String fromDateString = "Wed Jul 08 17:08:48 GMT 2009";
                  DateFormat formatter = new SimpleDateFormat
                      ("EEE MMM dd HH:mm:ss zzz yyyy");
                  Date fromDate = (Date)formatter.parse(fromDateString);
                  TimeZone central = TimeZone.getTimeZone("America/Chicago");
                  formatter.setTimeZone(central);
                  System.out.println(formatter.format(fromDate));
              }
          }
          

          输出:2009 年 7 月 8 日星期三 12:08:48 CDT

          【讨论】:

          • 遗憾的是,如果没有更多我想要处理的繁文缛节,我无法添加另一个依赖项。必须有一种方法可以使用标准 java 库来格式化时区。
          • 有,如答案中所示。如果您必须进行任何其他日期/时间操作,请期待更多的痛苦。
          • 它没有帮助。格式化程序总是输出 GMT 时间,而不是要求的 CDT。
          • 那么你使用了错误的时区 - 它在我的测试用例中运行良好。我将添加一个简短但完整的程序来演示。
          • 是的,你是对的......这很痛苦。一直有正确的代码,而我的单元测试中的拼写错误导致它无法正常工作。
          猜你喜欢
          • 2013-06-06
          • 1970-01-01
          • 2012-12-17
          • 1970-01-01
          • 1970-01-01
          • 2017-08-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多