如何为joda DateTime对象指定时区?

问题描述 投票:0回答:4

我有一个函数,可以将字符串转换为 joda 时间对象并格式化它。

public static String getFormattedDatetime(String someDate) {
    DateTime newDate = DateTime.parse(someDate, DateTimeFormat.forPattern("yy-MM-dd HH:mm:ss.SSS")).minusHours(7);
    String formattedDate = newDate.toString("dd-MMM-yy hh:mm a");

    return formattedDate;
}

该函数接受字符串并返回格式化的日期时间,但我在为其分配时区时遇到了麻烦。我传入的字符串表示数据库中的 UTC 时间,我需要将其转换为 PST/PDT。我想不出一种方法来 1) 为新的 DateTime 对象分配时区,2) 将该对象的时区转换为 PST/PDT。现在我正在用 .minusHours 处理这个问题。当然不理想。

java jodatime
4个回答
30
投票

在任何情况下都不应该使用

.minusHours(7)
,因为它半年都会出错,并且
DateTime
对象仍然会认为它是UTC。

使用

.withZone(DateTimeZone.forID("America/Los_Angeles"));

这里是 Joda Time 支持的所有时区及其对应 ID 的列表

我建议将

forID()
调用生成的常量重构为代码中适当位置的
static final
字段,并在需要进行转换的任何地方使用它。


您可能已经知道,但为了安全起见,

DateTime
对象是IMMUTABLE,这意味着
withZone
调用将返回一个全新的
DateTime
实例,并且不会更改原始的区域对象。


@anotherdave 在评论中提出了一个很好的观点。您在问题中说了

PST,但 PST 仅在半年中使用(因为夏令时)。我假设您指的是洛杉矶、西雅图等地的当前时间,而不是特指 PST 区域,因为这些城市在一年的另一半使用 PDT。但是,如果您确实 100% 想要 PST,则可以使用 forID("PST");


    


2
投票
更新:如果有人只想更改时区而不是实际日期。然后你可以使用下面的代码:

DateTime dateTime = DateTime.parse(date.toString(), DateTimeFormat.forPattern("yyyy-MM-dd")).withZoneRetainFields(DateTimeZone.forID("PST")); // it will change timezone to PST but not the actual date field value.
    

0
投票
已解决:

public static String getFormattedDatetime(String someDate) { DateTime newDate = DateTime.parse(someDate, DateTimeFormat.forPattern("yy-MM-dd HH:mm:ss.SSS")); LocalDateTime zonedDate = LocalDateTime.parse(newDate, DateTimeFormat.forPattern("yy-MM-dd HH:mm:ss.SSS")); DateTime finalZonedDate = zonedDate.toDateTime(DateTimeZone.UTC); String formattedDate = newDate.toString("dd-MMM-yy hh:mm a"); return formattedDate; }

当我将字符串转换为变量时,我必须使用 joda 的

LocalDateTime

 类来分配时区。然后我必须单独转换区域。


0
投票
PST(太平洋标准时间)和 PDT(太平洋夏令时间)是指时区

偏移

    PST:遵守标准时间时(11 月初至 3 月中旬)
  • PDT:遵守夏令时(3 月中旬至 11 月初)。
时区

offset 用于指定与 UTC 的固定偏移量。

另一方面,区域 ID,例如America/Los_Angeles 标识时区。因此,通过使用区域 ID,您可以确保生成的日期时间对象将自动考虑到

DST

接受的答案正确地提到:

在任何情况下都不应使用

.minusHours(7)


避免使用时区缩写

以下是

TimeZone

文档的摘录

三字母时区 ID

为了与 JDK 1.1.x 兼容,其他一些三字母时区 ID(例如“PST”、“CTT”、“AST”)是 也支持。然而,

它们的使用已被弃用,因为同样的 缩写通常用于多个时区(例如,“CST” 可以是美国“中部标准时间”和“中国标准时间”),以及 那么 Java 平台只能识别其中之一。

java.time

在我们进一步讨论之前,请查看

Joda-Time 主页上的以下通知:

请注意,从 Java SE 8 开始,用户被要求迁移到 java.time

 
(JSR-310) - JDK 的核心部分,它取代了这个 项目。

使用

java.time
 API 的解决方案

如果您使用格式为

yy-MM-dd HH:mm:ss.SSS

 的日期时间字符串,请注意它没有时区信息;因此,将其解析为 
LocalDateTime
 对象,然后使用 
LocalDateTime#atZone
.
添加时区信息。

或者,您可以使用

DateTimeFormatter#withZone

 (不是我最喜欢的)将日期时间字符串直接解析为 ZonedDateTime

演示:

public class Main { public static void main(String[] args) { ZoneId zoneId = ZoneId.of("America/Los_Angeles"); DateTimeFormatter parser = DateTimeFormatter.ofPattern("yy-MM-dd HH:mm:ss.SSS"); LocalDateTime ldt = LocalDateTime.parse("14-05-29 17:42:20.123", parser); ZonedDateTime zdt = ldt.atZone(zoneId); System.out.println(zdt); // Alternatively (not my favourite), DateTimeFormatter parserWithTz = DateTimeFormatter.ofPattern("yy-MM-dd HH:mm:ss.SSS") .withZone(zoneId); ZonedDateTime zdt2 = ZonedDateTime.parse("14-05-29 17:42:20.123", parserWithTz); System.out.println(zdt2); // A sample date-time DST is off System.out.println(LocalDateTime.parse("14-12-29 17:42:20.123", parser).atZone(zoneId)); // If you need the date-time with just the time zone offset OffsetDateTime odt = zdt.toOffsetDateTime(); System.out.println(odt); } }

输出:

2014-05-29T17:42:20.123-07:00[America/Los_Angeles] 2014-05-29T17:42:20.123-07:00[America/Los_Angeles] 2014-12-29T17:42:20.123-08:00[America/Los_Angeles] 2014-05-29T17:42:20.123-07:00
正如您在输出中看到的,

ZonedDateTime

对象自动在区域偏移量 -07:00 和 -08:00 之间切换。

在线演示

Trail:日期时间了解有关现代日期时间 API 的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.