【问题标题】:joda time to Date inconsistent time zonesjoda time to Date 时区不一致
【发布时间】:2015-09-23 18:35:19
【问题描述】:

我有很多日期想存储在使用 BST 的服务器上运行的数据库中:

  1. 2015-09-23
  2. 2024-05-07
  3. 2024-03-13

但是它们在数据库中存储为:

  1. 2015-09-23 01:00:00
  2. 2024-05-07 01:00:00
  3. 2024-03-13 00:00:00 01:00:00

值在存储到数据库之前转换为Date。我在调试时注意到以下几点:

TimeZone timeZone = Calendar.getInstance().getTimeZone();
System.out.println(timeZone.getDisplayName(false, TimeZone.SHORT));

System.out.println(new SimpleDateFormat("zzz").format(new Date()));

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd").withZone(DateTimeZone.UTC);
System.out.println(formatter.parseDateTime("2015-09-23").toDate());
System.out.println(formatter.parseDateTime("2024-05-07").toDate());
System.out.println(formatter.parseDateTime("2024-03-13").toDate());

前两个日期使用BST,最后一个日期使用GMT。是否可以让它们都使用相同的时区?

GMT
BST
Wed Sep 23 01:00:00 BST 2015
Tue May 07 01:00:00 BST 2024
Wed Mar 13 00:00:00 GMT 2024

【问题讨论】:

  • 他们不是使用相同的时区,而是分别使用夏季和冬季时间吗?
  • 冬天没有英国夏令时!您可以将它们全部设为 GMT。也许formatter.parseDateTime("2024-03-13").toDateTime(DateTimeZone.UTC).toLocalDate() #toDate() 提供了一个 java.util.Date 类型,它取决于 JVM 设置。但是#toLocalDate() 留在jodatime 里面。请注意,在您的代码中,您只在要解析的格式上设置时区,而不是打印出 java.util.Date。

标签: java timezone jodatime


【解决方案1】:

首先,请记住java.util.Date 没有时区(有关它的更多详细信息可以阅读here)。

发生的情况是Date.toString() 方法使用系统的默认时区来打印其值(检查您的JVM 中TimeZone.getDefault() 的值,它可能是Europe/London)。

Europe/London 时区,偏移量在冬季等于UTC(打印为GMT),在夏季为+01:00(打印为@987654333 @,又名British Summer Time)。这些不同的 3 个字母名称表示偏移量的变化,但这并不意味着日期“改变”了它们的时区。

还要考虑 timezone 不仅仅是偏移量或名称,而是the set of all offset changes that occur in a region during history(发生更改时,以及每次更改前后的偏移量)。

所以,日期没有不同的时区,因为:

  1. 在同一个时区可以有多个偏移量。并且偏移量的一些变化会导致 3 字母名称的变化——虽然这些 3 字母名称的使用被广泛使用,但它们是 ambiguous and not standard
  2. java.util.Date doesn't have a timezone,所以改不了了。

如果您想将这些对象保存在数据库中,您应该关心的是时间戳(从1970-01-01T00:00:00Z 开始的毫秒数),它在转换为Date 时会保留下来。

如果您检查创建的对象中的时间戳毫秒,您会发现它没有更改:

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd").withZone(DateTimeZone.UTC);
DateTime d1 = formatter.parseDateTime("2015-09-23");
DateTime d2 = formatter.parseDateTime("2024-05-07");
DateTime d3 = formatter.parseDateTime("2024-03-13");

// comparing timestamp millis between DateTime and java.util.Date
System.out.println(d1.getMillis() == d1.toDate().getTime());
System.out.println(d2.getMillis() == d2.toDate().getTime());
System.out.println(d3.getMillis() == d3.toDate().getTime());

上面的所有 3 个案例都打印 true,这意味着它们代表同一时刻(因此日期没有改变)。

实际上,您可以看到所有DateTime 对象都是UTC:

System.out.println(d1);
System.out.println(d2);
System.out.println(d3);

打印出来:

2015-09-23T00:00:00.000Z
2024-05-07T00:00:00.000Z
2024-03-13T00:00:00.000Z

结论:

  • 您可以毫无问题地保存 Date 对象,因为它们的值是正确的
  • 如果你想向用户显示日期,你可以使用DateTime对象(如果你想要不同的格式,可以使用DateTimeFormatter),因为它们不使用默认的TimeZone toString() 方法。

【讨论】:

    【解决方案2】:

    试试这个: SimpleTimeZone UTCTimeZone = new SimpleTimeZone(0, "UTC"); TimeZone.setDefault(UTCTimeZone); 所有日期对象都将使用 UTC 作为后端代码的默认时区

    【讨论】:

      猜你喜欢
      • 2014-08-22
      • 2012-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      相关资源
      最近更新 更多