更改日期对象的时区而不更改日期

问题描述:

我可以在不更改日期的情况下更改我的java代码中Date对象的时区吗? 当我写 Date date = new Date(longValue); 我在我的当地时区得到这个日期。我想得到这个日期,但我的时区应该是我的用户ID(例如“America/Chicago”)在DB(不是本地)中出现的时区。更改日期对象的时区而不更改日期

在此先感谢您的帮助。

+0

始终使用UTC时间在数据库中保存日期,并且您可以在需要时获取任何时区日期。 –

TL;博士

ZonedDateTime zdtMontreal = 
    ZonedDateTime.now(ZoneId.of("America/Montreal")); 

ZonedDateTime zdtAuckland = 
    zdtMontreal.withZoneSameLocal(ZoneId.of("Pacific/Auckland")); 

同一时刻。zdtAuckland时刻

要确定这是你的意图。我对你做错事感到心有余悸,对日期时间处理的工作方式感到困惑。日期时间工作混淆。一定要搜索和研究堆栈溢出。

java.time

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

Local…类故意没有时区或offset-from-UTC信息。

LocalDate ld = LocalDate.of(2016 , Month.January , 23); // 2016-01-23 
LocalTime lt = LocalTime.of(12 , 34 , 56); // 12:34:56 

这些值尚未代表时间轴上的一个点。那是奥克兰新西兰,巴黎FR还是蒙特利尔CA的中午时间?我们必须应用时区来确定实际时刻。我们应用ZoneId获得ZonedDateTime

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

ZoneId zMontreal = ZoneId.of("America/Montreal"); 
ZonedDateTime zdtMontreal = ZonedDateTime.of(ld , lt , zMontreal); 

要看到代表在标准ISO 8601格式该值的字符串,调用toString。实际上,ZonedDateTime类通过在方括号中明智地附加时区名称来扩展标准格式。

String outputMontreal = zdtMontreal.toString(); 

2016-01-23T12:34:56-05:00 [美国/蒙特利尔]

要获得相同的日期和时间相同的日另一个时区,重复这个过程。

ZoneId zParis = ZoneId.of("Europe/Paris"); 
ZonedDateTime zdtParis = ZonedDateTime.of(ld , lt , zParis); 

ZoneId zAuckland = ZoneId.of("Pacific/Auckland"); 
ZonedDateTime zdtAuckland = ZonedDateTime.of(ld , lt , zAuckland); 

但是知道你在时间上得到一个不同时刻。奥克兰中午发生在巴黎中午前几个小时,而在蒙特利尔中午甚至更晚,因为三个不同时间点碰巧分享巧合wall-clock time

2016-01-23T12:34:56-05:00 [美国/蒙特利尔]

2016-01-23T12:34:56 + 01:00 [欧洲/巴黎]

2016-01-23T12:34:56 + 13:00 [太平洋/奥克兰]

enter image description here

当前时刻

要获得当前时刻,请致电Instant.nowInstant类表示UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数点后最多九位数字)。

Instant instance = Instance.now(); 

ZoneId应用于调整到一个时区。

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = instance.atZone(z); 

对其他所需时区重复此过程,与我们在上面做的类似。

作为快捷方式,您可以直接获得ZonedDateTime

ZonedDateTime zdtMontreal = ZonedDateTime.now(ZoneId.of("America/Montreal")); 

而作为另一种快捷方式,可以采用不同的时区,同时保持相同的日期和时间相同的日(相同挂钟时间)。致电ZonedDateTime::withZoneSameLocal

ZonedDateTime zdtAuckland = zdtMontreal.withZoneSameLocal(ZoneId.of("Pacific/Auckland")); 

我再说一遍:这导致是在时间线上不同点。 zdtAuckland正在zdtMontreal发生前几个小时发生。

要保持同一时刻,请拨打ZonedDateTime::withZoneSameInstant

数据库

平时最好存储在数据库中UTC您的日期时间值。已经在Stack Overflow上进行了广泛的讨论。搜索更多信息。


关于java。时间

java.time框架内置于Java 8及更高版本中。这些类别取代了日期时间类别legacy,如java.util.Date,Calendar,& SimpleDateFormat

Joda-Time项目现在在maintenance mode中,建议迁移到java.time。请致电Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。规格是JSR 310

从何处获取java.time类?

ThreeTen-Extra项目与其他类扩展java.time。这个项目是未来可能增加java.time的一个试验场。您可以在这里找到一些有用的类,例如Interval,YearWeek,YearQuartermore

你会发现ZonedDateTime非常有帮助:

Java 8 Convert given time and time zone to UTC time

另外,您可以创建另一个Date对象,并应用一些手动偏移到它。

+0

我已经尝试过,但它并没有解决我的问题。我只想改变我的时区而不是约会。例如,我希望将这个日期11/23/2016,4:16 PM EST更改为2016/11/23,4:16 PM CST。这可能吗? – user3334226

如何使用Java8 ZonedDateTime类做一个例子:

Date date = new Date(longValue); 
ZoneId = ZoneId.of("America/Chicago"); 
ZonedDateTime dt = ZonedDateTime.ofInstant(date.toInstant(), zoneId); 

您已经标记了与乔达的问题,但真正与Java8你不需要它了。

+0

我已经尝试过,但它没有解决我的问题。我只想改变我的时区而不是约会。例如,我希望将这个日期11/23/2016,4:16 PM EST更改为2016/11/23,4:16 PM CST。你的例子也改变了日期。 – user3334226