Java GregorianCalendar 更改时区
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12137428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java GregorianCalendar change TimeZone
提问by Alexander Allakhverdiyev
I'm trying to set HOUR_OF_DAY field and change Timezone of the GregorianCalendar date object.
我正在尝试设置 HOUR_OF_DAY 字段并更改 GregorianCalendar 日期对象的时区。
GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));
date.set(Calendar.HOUR_OF_DAY, 23);
//date.get(Calendar.HOUR_OF_DAY);
date.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));
Output:
输出:
HOUR: 16
HOUR: 23
For some reason value of HOUR_OF_DAY does not change after setting different timezone. But if I uncomment date.get for HOUR_OF_DAY, everything works exactly as it should
由于某种原因,HOUR_OF_DAY 的值在设置不同的时区后不会改变。但是如果我在 HOUR_OF_DAY 取消注释 date.get,则一切都完全正常
GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));
date.set(Calendar.HOUR_OF_DAY, 23);
date.get(Calendar.HOUR_OF_DAY); // uncommenting this line will is changing the output
date.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));
Output:
输出:
HOUR: 16
HOUR: 13
How is this possible? Why .get method is changing object behaviour?
这怎么可能?为什么 .get 方法正在改变对象行为?
回答by Bill the Lizard
The GregorianCalendar
class inherits its get
method from Calendar
, which has the following side effect:
的GregorianCalendar
类继承其get
从方法Calendar
,其具有以下副作用:
In lenient mode, all calendar fields are normalized.
在宽松模式下,所有日历字段都被标准化。
This means that the time
value and all fields are recomputed when get
is called on a Calendar
object. This can lead to some unpredictable behavior, particularly when coupled with setTimeZone
, which has some documented buggy behaviorof its own.
这意味着在对象上调用time
时会重新计算值和所有字段。这可能会导致一些不可预测的行为,特别是当与 结合使用时,它本身有一些记录在案的错误行为。get
Calendar
setTimeZone
回答by Basil Bourque
tl;dr
tl;博士
OffsetDateTime.now( ZoneOffset.ofHours( 10 ) ).withHour( 23 )
Avoid legacy date-time classes
避免遗留的日期时间类
The legacy date-time classes including GregorianCalendar
are a confusing. awkward, poorly-design mess. Avoid them. Now supplanted by the java.timeclasses. Specifically, GregorianCalendar
is replaced by ZonedDateTime
.
遗留的日期时间类包括GregorianCalendar
令人困惑。尴尬,设计糟糕的一团糟。避开它们。现在被java.time类取代。具体来说,GregorianCalendar
由 代替ZonedDateTime
。
Offset-from-UTC
UTC 偏移量
You apparently want a moment with an offset-from-UTCof ten hours ahead of UTC. Define your desired offset.
您显然想要比UTC早十小时的UTC偏移量。定义所需的偏移量。
ZoneOffset offset = ZoneOffset.ofHours( 10 ) ;
offset.toString(): +10:00
offset.toString(): +10:00
Get the current moment as an OffsetDateTime
with that offset.
获取OffsetDateTime
具有该偏移量的当前时刻。
OffsetDateTime odt = OffsetDateTime.now( offset ) ;
odt.toString(): 2018-02-15T16:44:44.216642+10:00
odt.toString(): 2018-02-15T16:44:44.216642+10:00
You want to override the hour to be 23
.
您想将小时覆盖为23
。
OffsetDateTime odt23 = odt.withHour( 23 ) ;
odt23.toString(): 2018-02-15T23:44:44.216642+10:00
odt23.toString(): 2018-02-15T23:44:44.216642+10:00
Time zone
时区
I'm trying to set HOUR_OF_DAY field and change Timezone of the GregorianCalendar date object.
我正在尝试设置 HOUR_OF_DAY 字段并更改 GregorianCalendar 日期对象的时区。
Nope, you are changing the offset-from-UTC, not the time zone.
不,您正在更改offset-from-UTC,而不是time zone。
Always better to use a time zone rather than a mere offset, if you know for certainthe intended zone. A time zone is a history of past, present, and future changes to the offset used by the people of a certain region. With a time zone you can always determine the offset, but not vice-versa.
如果您知道特定的预期区域,那么使用时区而不是单纯的偏移总是更好。时区是某个地区的人们使用的偏移量的过去、现在和未来变化的历史。使用时区,您始终可以确定偏移量,但反之则不然。
Specify a proper time zone namein the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are nottrue time zones, not standardized, and not even unique(!).
以、、 或等格式指定正确的时区名称。永远不要使用 3-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/region
America/Montreal
Africa/Casablanca
Pacific/Auckland
EST
IST
ZoneId z = ZoneId.of( "Australia/Brisbane" ) ;
Capture the current moment in a wall-clock time seen by the people of that zone.
在该区域的人们看到的挂钟时间中捕捉当前时刻。
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Override the hour-of-day.
覆盖一天中的小时。
ZonedDateTime zdt23 = zdt.withHour( 23 ) ;
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
Using a JDBC drivercompliant with JDBC 4.2or later, you may exchange java.timeobjects directly with your database. No need for strings nor java.sql.* classes.
使用符合JDBC 4.2或更高版本的JDBC 驱动程序,您可以直接与您的数据库交换java.time对象。不需要字符串或 java.sql.* 类。
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android, the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 更高版本的 Android 捆绑实现 java.time 类。
- 对于早期的 Android,ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。