java 日历返回错误时区的日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26678030/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:23:06  来源:igfitidea点击:

Calendar returns date in wrong time zone

javadatedatetime

提问by Dónal

If I execute the following on a computer in the GMT timezone

如果我在 GMT 时区的计算机上执行以下操作

TimeZone timeZone = TimeZone.getTimeZone('IST');  // India Standard Time
Calendar calendar = Calendar.getInstance(timeZone);

System.out.println(calendar.getTime());

It prints

它打印

Fri Oct 31 15:18:22 GMT 2014

格林威治标准时间 2014 年 10 月 31 日星期五 15:18:22

Why is the date printed in the computer's default time zone, rather than the TimeZonethe Calendarwas constructed with?

为什么日期印在计算机的默认时区,而不是TimeZoneCalendar与构建?

采纳答案by Jigar Joshi

because Dateobject doesn't have timezone as part of its state, You need SimpleDateFormat to format and print the date in your required timezone

因为Date对象没有时区作为其状态的一部分,您需要 SimpleDateFormat 以您所需的时区格式化和打印日期

回答by Basil Bourque

The Answer by Joshiis correct but brief. I'll expand a bit, and show an alternative with modern classes.

Joshi回答是正确但简短的。我将扩展一点,并展示现代类的替代方案。

Datehas no time zone

Date没有时区

Your code calendar.getTime()extracts a java.util.Dateobject from the java.util.Calendarobject.

您的代码从对象中calendar.getTime()提取一个对象。java.util.Datejava.util.Calendar

The java.util.Dateclass has a well-intentioned but confusing feature where its toStringmethod applies the JVM's current default time zone while generating the string. This creates the illusion that the Dateclass has a time zone when it does not. A Daterepresents a moment on the timeline as a count of milliseconds since the epoch reference date of first moment of 1970 UTC (1970-01-01T00:00:00Z). (Even more confusing, the Dateclass actually doeshave a time zone nestled deep inside, but is unreachable and irrelevant to this discussion.)

java.util.Date班有一个善意的,但令人困惑的功能,使它的toString方法适用于JVM的当前默认时区而产生的字符串。这会造成Date班级有时区而没有时区的错觉。ADate表示时间轴上的一个时刻,作为自 1970 UTC ( 1970-01-01T00:00:00Z)的第一个时刻的纪元参考日期以来的毫秒计数。(更令人困惑的是,Date该类实际上确实有一个位于内部深处的时区,但无法访问且与本次讨论无关。)

Avoid legacy date-time classes

避免遗留的日期时间类

The old date-time classes are now legacy, supplanted by the java.time classes. Instead use only the java.time classes.

旧的日期时间类现在是遗留的,被 java.time 类取代。而是仅使用 java.time 类。

Instant

Instant

For a moment in UTC, the equivalent to java.util.Date, use the Instantclass. The Instantclass represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).

在 UTC 中,相当于java.util.Date, 使用Instant该类。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

Instant instant = Instant.now();  // Current moment in UTC.

ZonedDateTime

ZonedDateTime

To view the same moment through the lens of a particular region's wall-clock time, apply a ZoneIdto get a ZonedDateTime.

要通过特定区域挂钟时间的镜头查看同一时刻,请应用 aZoneId以获取ZonedDateTime.

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 ESTor ISTas they are nottrue time zones, not standardized, and not even unique(!).

以、、 或等格式指定正确的时区名称。永远不要使用 3-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );

Search Stack Overflow for many other Questions and Answers on this topic. This Question is really a duplicate of many others.

在 Stack Overflow 上搜索有关此主题的许多其他问题和答案。这个问题实际上是许多其他问题的重复。



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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

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 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by Barnesy

When converting the Calendar object to a Date object the timezone is lost. Calendar itself uses the timezone. The following prints to the specified timezone.

将 Calendar 对象转换为 Date 对象时,时区会丢失。日历本身使用时区。以下打印到指定的时区。

TimeZone timeZone = TimeZone.getTimeZone('IST');  // India Standard Time
Calendar calendar = Calendar.getInstance(timeZone);

System.out.println(calendar.get(Calendar.DAY_OF_MONTH) + "/" + 
(calendar.get(Calendar.MONTH)+1) + "/" + calendar.get(Calendar.YEAR) + " Time: " + 
calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));
 System.out.println(calendar.getTime());

(Note do not use the Calendar API like this, its very messy. Use the date formatting api)

(注意不要像这样使用日历 API,它非常混乱。使用日期格式 api)

The Date api has many issues (that's why its been completely redone in java 8).

Date api 有很多问题(这就是它在 java 8 中完全重做的原因)。

回答by prsutar

you have to apply timezone before you print the date/time

您必须在打印日期/时间之前应用时区

example: TimeZone.setDefault(TimeZone.getTimeZone("IST"));

示例: TimeZone.setDefault(TimeZone.getTimeZone("IST"));

(code not tested)

(代码未测试)

回答by SparkOn

Calendar#getTime()- Returns a Date object representing this Calendar's time value (millisecond offset from the Epoch.To be precise the value within a java.util.Date is the number of milliseconds since the Unix epoch, which occurred at midnight January 1st 1970, UTC. and java.util.Date is has no specific time zone.

Calendar#getTime()- 返回一个 Date 对象,表示这个 Calendar 的时间值(从纪元的毫秒偏移量。准确地说,java.util.Date 中的值是自 Unix 纪元以来的毫秒数,它发生在 1 月 1 日午夜1970 年,UTC. 和 java.util.Date 没有特定的时区。

on the other hand you can achieve what you are trying to do in this way also

另一方面,您也可以通过这种方式实现您想要做的事情

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("IST"));
System.out.println(sdf.format(new Date()));