【问题标题】:Java timezone - strange behavior with IST?Java 时区 - IST 的奇怪行为?
【发布时间】:2012-07-01 03:46:03
【问题描述】:

我有以下代码:

DateFormat df = new SimpleDateFormat("M/d/yy h:mm a z");
df.setLenient(false);
System.out.println(df.parse("6/29/2012 5:15 PM IST"));

假设我现在将 PC 的时区设置为太平洋时间(PDT 为 UTC-7),这将打印出来

2012 年 6 月 29 日星期五 08:15:00 PDT

PDT 不是比 IST(印度标准时间)晚 12.5 小时吗?任何其他时区都不会出现此问题 - 我在日期字符串中尝试了 UTC、PKT、MMT 等而不是 IST。 Java中是否有两个IST?

P.S:实际代码中的日期字符串来自外部来源,所以我不能使用 GMT 偏移量或任何其他时区格式。

【问题讨论】:

  • 据我所知,有几个 IST。从时差(9 小时)来看,您可能使用的是以色列标准时间。
  • @biziclop 我想到了这个。但是让我偏离了这一点的是以下内容:System.out.println(TimeZone.getTimeZone("IST").getRawOffset()); 这将打印 19800000 或 5.5 小时,这表明它确实是印度标准时间。还是它选择了具有相同 ID“IST”的许多时区中的第一个?如果是这样,如果一个东西对很多东西都是一样的,那它怎么可能是一个“ID”呢?
  • @esej 更可能是时区缩写不明确:en.wikipedia.org/wiki/List_of_time_zone_abbreviations
  • source code好像IST是印度...
  • @Vasan 这不是一个真正的 ID,SimpleDateFormat 是一个奇怪的野兽,很可能它根本没有使用 TimeZone.getTimeZone()

标签: java timezone


【解决方案1】:

这是因为 IST 将具有多种含义,例如爱尔兰标准时间、以色列标准时间、印度标准时间。

参考:https://www.timeanddate.com/time/zones/

使用 setTimezone() 方法专门设置时区。

例如:parser.setTimeZone(TimeZone.getTimeZone("这里详细指定时区"));

【讨论】:

    【解决方案2】:

    时区的缩写名称不明确,并且已弃用 Olson 时区名称。以下内容始终如一,因为 parse() 和 getTimezone() 的行为方式可能有所不同。

    SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm a Z");
    TimeZone istTimeZone = TimeZone.getTimeZone("Asia/Kolkata");
    Date d = new Date();
    sdf.setTimeZone(istTimeZone);
    String strtime = sdf.format(d);
    

    【讨论】:

      【解决方案3】:

      不是答案,但请参阅下面的输出 + 代码 - 似乎 parse 对待 IST 的方式与 TimeZone.getTimeZone("IST") 不同...

      2012 年 6 月 29 日星期五 16:15:00 BST
      2012 年 6 月 29 日星期五 12:45:00 BST
      2012 年 6 月 29 日星期五 12:45:00 BST
      *BST = 伦敦

      public static void main(String[] args) throws InterruptedException, ParseException {
          DateFormat fmt1 = new SimpleDateFormat("M/d/yy h:mm a Z");
          Date date = fmt1.parse("6/29/2012 5:15 PM IST");
          System.out.println(date);
      
          DateFormat fmt2 = new SimpleDateFormat("M/d/yy h:mm a");
          fmt2.setTimeZone(TimeZone.getTimeZone("IST"));
          System.out.println(fmt2.parse("6/29/2012 5:15 PM"));
      
          DateFormat fmt3 = new SimpleDateFormat("M/d/yy h:mm a");
          fmt3.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
          System.out.println(fmt3.parse("6/29/2012 5:15 PM"));
      }
      

      【讨论】:

      • 是的,这正是我所说的。 SimpleDateFormat 是一头奇怪的野兽,不按规则行事。它有自己的时区数据数组,并使用其中首先出现的任何内容。
      【解决方案4】:

      对不起,我必须为此写一个答案,但试试这个代码:

      public class Test {
      
          public static void main(String[] args) throws ParseException {
              DF df = new DF("M/d/yy h:mm a z");
              String [][] zs = df.getDateFormatSymbols().getZoneStrings();
              for( String [] z : zs ) {
                  System.out.println( Arrays.toString( z ) );
              }
          }
      
          private static class DF extends SimpleDateFormat {
              @Override
              public DateFormatSymbols getDateFormatSymbols() {
                  return super.getDateFormatSymbols();
              }
      
              public DF(String pattern) {
                  super(pattern);
              }
          }
      
      }
      

      您会发现 IST 在列表中出现了好几次,第一个确实是以色列标准时间。

      【讨论】:

      • 谢谢,这很有帮助。我想那时我必须做一些奇怪的事情,比如在解析它之前从日期字符串中剥离时区。然后我可以将时区部分传递给 TimeZone.getTimeZone() 以获取实际的时区(我想即使这样也不能保证总是有效!)。现在一切都变得不完整了,该死的 DateFormat!
      • @Vasan 好吧,DateFormat 不是这里唯一的罪魁祸首,基本问题是时区首字母缩写词不是唯一的。事后看来,这是一个愚蠢的想法。 :)
      猜你喜欢
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2018-08-15
      相关资源
      最近更新 更多