我需要在我的项目中从一个时区转换为另一个时区。
我可以从当前时区转换为另一个时区,但不能从不同时区转换为另一个时区。
例如,我在印度,我可以使用 Date d=new Date();
从印度转换为美国,并将其分配给日历对象并设置时区。
但是,我无法从不同时区到另一个时区执行此操作。例如,我在印度,但在将时区从美国转换为英国时遇到问题。
I need to convert from one timezone to another timezone in my project.
I am able to convert from my current timezone to another but not from a different timezone to another.
For example I am in India, and I am able to convert from India to US using Date d=new Date();
and assigning it to a calendar object and setting the time zone.
However, I cannot do this from different timezone to another timezone. For example, I am in India, but I am having trouble converting timezones from the US to the UK.
发布评论
评论(13)
tl;dr
详细信息
java.util.Date 类没有分配时区†,但它的
toString
实现却混淆地应用了 JVM 当前的默认时区。避免 java.util.Date & .Calendar
这是避免与 Java 捆绑在一起的众所周知的麻烦的 java.util.Date、.Calendar 和 SimpleDateFormat 类的众多原因之一。避开他们。而是使用:
java.time
Java 8 及更高版本具有 java.time 包 内置。这个包的灵感来自 Joda-Time。虽然它们有一些相似之处和类名,但它们是不同的;每个都有另一个所缺乏的功能。一个显着的区别是 java.time 避免使用构造函数,而是使用静态实例化方法。这两个框架均由同一个人 Stephen Colbourne 领导。
许多 java.time 功能已向后移植到 Java 6 和 Java 6。 ThreeTen-Backport 项目中的 7 号。在ThreeTenABP项目中进一步适配Android。
就这个问题而言,它们以相同的方式工作。指定时区,并调用
now
方法获取当前时刻,然后基于旧的不可变实例创建一个新实例以调整时区。请注意两个不同的时区类别。一个是指定时区,包括夏令时和其他此类异常的所有规则以及与 UTC 的偏移量,而另一个只是偏移量。
Joda-Time
Joda-Time 2.3 中的一些示例代码如下。在 StackOveflow 中搜索更多示例和讨论。
我们对宇宙时间线上的同一时刻有四种表示。
†实际上,
java.util.Date
类确实有一个时区隐藏在其源代码。但出于大多数实际目的,该类会忽略该时区。因此,作为简写,人们常说 juDate 没有指定时区。令人困惑?是的。避免 juDate 的混乱,并使用 Joda-Time 和/或 java.time。tl;dr
Details
The java.util.Date class has no time zone assigned†, yet it's
toString
implementation confusingly applies the JVM's current default time zone.Avoid java.util.Date & .Calendar
This is one of many reasons to avoid the notoriously troublesome java.util.Date, .Calendar, and SimpleDateFormat classes bundled with Java. Avoid them. Instead use either:
java.time
Java 8 and later has the java.time package built-in. This package was inspired by Joda-Time. While they share some similarities and class names, they are different; each has features the other lacks. One notable difference is that java.time avoids constructors, instead uses static instantiation methods. Both frameworks are led by the same man, Stephen Colbourne.
Much of the java.time functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project. Further adapted to Android in the ThreeTenABP project.
In the case of this Question, they work in the same fashion. Specify a time zone, and call a
now
method to get current moment, then create a new instance based on the old immutable instance to adjust for time zone.Note the two different time zone classes. One is a named time zone including all the rules for Daylight Saving Time and other such anomalies plus an offset from UTC while the other is only the offset.
Joda-Time
Some example code in Joda-Time 2.3 follows. Search StackOveflow for many more examples and much discussion.
We have four representations of the same moment in the timeline of the Universe.
†Actually the
java.util.Date
class does have a time zone buried within its source code. But the class ignores that time zone for most practical purposes. So, as shorthand, it’s often said that j.u.Date has no time zone assigned. Confusing? Yes. Avoid the mess that is j.u.Date and go with Joda-Time and/or java.time.一些示例
在时区之间转换时间
时区之间的时间转换
Some examples
Convert time between timezone
Converting Times Between Time Zones
只需为
Calendar
对象设置适当的时区即可完全避免“默认”时区。不过,我个人建议您使用 Joda Time 作为 Java 中日期和时间操作的高级 API 。除此之外,时区转换在 Joda 中非常简单。目前尚不清楚您当前的代码是什么样的,以及为什么您只能通过默认时区进行转换,但在 Joda Time 中,您只需在创建(例如)
DateTime
对象,然后使用withZone(日期时区区)
。如果您能告诉我们更多有关如何获取输入数据的信息,我们可以给出更完整的示例。
The "default" time zone can be avoided entirely by just setting the time zone appropriately for the
Calendar
object. However, I would personally suggest that you use Joda Time as a far superior API for date and time operations in Java. Amongst other things, time zone conversion is very simple in Joda.It's not clear what your current code looks like and why you're only able to convert via the default time zone, but in Joda Time you'd just specify the time zone explicitly when creating (say) a
DateTime
object, and then usewithZone(DateTimeZone zone)
.If you could tell us more about how you're getting input data, we could give a fuller example.
您可以使用以下代码片段
You can use the following code snippet
如果您不想使用 Joda,这里有一种使用内置库的确定性方法。
首先,我建议您强制 JVM 默认为时区。这解决了当您将 JVM 从一台机器移动到另一台设置为不同时区的机器时可能遇到的问题,但源数据始终是特定时区。例如,假设您的数据始终为 PDT/PST 时区,但您在设置为 UTC 时区的机器上运行。
以下代码片段在我的 JVM 中设置默认时区:
现在假设您的源日期以 PDT/PST 形式输入,但您需要将其转换为 UTC。这些是步骤:
输出将是:
If you don't want to use Joda, here is a deterministic way using the built in libraries.
First off I recommend that you force your JVM to default to a timezone. This addresses the issues you might run into as you move your JVM from one machine to another that are set to different timezones but your source data is always a particular timezone. For example, lets say your data is always PDT/PST time zone, but you run on a box that is set to UTC timezone.
The following code snippet sets the default timezone in my JVM:
Now lets say your source date is coming in as PDT/PST but you need to convert it to UTC. These are the steps:
The output would be:
java.time
java.util
Date-Time API 及其格式化 APISimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 现代日期时间 API*。另外,下面引用的是 Joda-Time 主页上的通知:
如何切换到现代 API?
使用
Date#toInstant
例如,Instant
与我的要求有什么关系?即时
代表 UTC 时间线上的瞬时点。示例输出中的Z
是 时区指示符零时区偏移。它代表 Zulu,指定Etc/UTC
时区(时区偏移量为+00:00
小时)。它的零时区偏移使其独立于时区,即世界上每个地方的瞬间都是相同的。它类似于物质世界中的水。您可以通过调用 ZoneId)与
Instant
混合使用/java/time/Instant.html#atZone-java.time.ZoneId-" rel="nofollow noreferrer">Instant.atZone
获取该时区相应的日期时间( IEZonedDateTime
)。同样,您可以通过调用
Instant#atOffset
获取相应的日期时间该时区偏移量(即OffsetDateTime
)。相反的方式,您还可以通过在
ZonedDateTimetoInstant
来获取Instant
code> 或OffsetDateTime
。输出:
到目前为止,您已经学会了一种简单的方法来转换
Instant
(您直接创建或获得从java.util.Date
或ZonedDateTime
或OffsetDateTime
)到任何时区或任何时区偏移的日期时间。或者,
还有另一种方法将
ZonedDateTime
从一个时区转换为另一个时区。同样,有一种类似的方法可以将OffsetDateTime
从一个时区偏移量转换为另一个时区偏移量。输出:
何时使用
ZonedDateTime
以及何时使用OffsetDateTime
?02:00
小时,请使用OffsetDateTime
。所有 JDBC 驱动程序也都支持它。查看此答案以了解更多信息。ZonedDateTime.不幸的是,JDBC 不支持
ZonedDateTime
。了解有关
java.time
的更多信息,现代日期时间 API* 来自 跟踪:日期时间。* 无论出于何种原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport 将大部分 java.time 功能向后移植到 Java 6 和 Java 6 7. 如果您正在处理 Android 项目,并且您的 Android API 级别仍然不符合 Java-8,请检查 通过脱糖提供 Java 8+ API 和 如何在Android项目中使用ThreeTenABP。
java.time
The
java.util
Date-Time API and their formatting API,SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.Also, quoted below is a notice at the Home Page of Joda-Time:
How to switch to the modern API?
Convert
java.util.Date
toInstant
usingDate#toInstant
e.g.What's
Instant
got to do with my requirement?An
Instant
represents an instantaneous point on the timeline in UTC. TheZ
in the sample output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies theEtc/UTC
timezone (which has the timezone offset of+00:00
hours). Its zero-timezone offset makes it independent of timezones i.e. an instant is the same at every place in the world. It's analogous to water in the physical world.You can mix a timezone (i.e.
ZoneId
) with anInstant
by callingInstant.atZone
to get the corresponding Date-Time in that timezone (i.e.ZonedDateTime
).Similarly, you can mix a timezone offset (i.e.
ZoneOffset
) with anInstant
by callingInstant#atOffset
to get the corresponding Date-Time with that timezone offset (i.e.OffsetDateTime
).In the reverse way, you can also get an
Instant
by callingtoInstant
on theZonedDateTime
orOffsetDateTime
.Output:
So far you have learnt a simple way to convert an
Instant
(which you have created directly or obtained from ajava.util.Date
or aZonedDateTime
or anOffsetDateTime
) to a Date-Time in any timezone or at any timezone offset.Alternatively
There is another way to convert a
ZonedDateTime
from one timezone to another. Again, there is a similar method to convert anOffsetDateTime
from one timezone offset to another.Output:
When to use
ZonedDateTime
and when to useOffsetDateTime
?02:00
hours, useOffsetDateTime
. It is also supported by all JDBC drivers. Check this answer to learn more about it.ZonedDateTime
. Unfortunately,ZonedDateTime
is not supported by JDBC.Learn more about
java.time
, the modern Date-Time API* from Trail: Date Time.* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
您可以使用 java.time.ZoneDateTime#ofInstant() 方法:
You could use the
java.time.ZoneDateTime#ofInstant()
method:取决于“转换”的真正含义。
它可能就像在格式化程序中设置时区一样简单,并且根本不与日历混淆。
Depends on what you really mean by "converting".
It MAY be as simple as setting the time zone in the FORMATTER, and not mucking with Calendar at all.
这不是答案,但可以帮助尝试生成具有相同时区的日期并应用另一个时区偏移量的人。
当您的应用程序服务器在一个时区运行而数据库在另一个时区运行时,它非常有用。
This is not the answer, but could help someone trying to generate dates with same timezone and apply another timezone's offset.
It is useful when your application server is running in one timezone and your database in another.
您可以执行类似的操作来获取另一个时区的当前时间。
You can do something like this to get the current time in another time zone.
这里有一个故事:
我在美国的用户在网页中输入日期。我的服务器将其作为 java.util.Date 对象获取。
Date
对象没有时区的概念。假设用户输入晚上 11 点(== 伦敦时间凌晨 4 点)。对她来说,现在是美国时间晚上 11 点。
您的服务器收到此消息并将其解释为 JVM 时区的晚上 11 点。
但您需要的是一个代表凌晨 4 点的
Date
对象。here a story:
my user in US enters a date in a web page. My server gets this as a
java.util.Date
object.Date
objects have no notion of time zone.so let's say user entered 11PM(== 4AM london time). For her this was 11PM US time.
Your server gets this and interprets this as 11PM of JVM's timezone.
but what you need is a
Date
object that represents 4AM.要将任何时间转换为具有任何时间模式的特定时区(例如:UTC -> 本地时区,反之亦然),您可以使用 java.time 库。
此方法将采用时间模式(原始格式和所需格式)和时区(原始时区和所需时区)将给出字符串作为输出。您可以使用 SimpleDateFormatter 将 String 转换为日期,也可以使用 ZoneDateTime/Instant 类的 parse 方法。
将字符串转换为日期:
将日期转换为字符串:
To convert any time to the specific timezone (for example: UTC -> local timezone and vise versa) with any time pattern you can use java.time library.
This method will take time patterns (original and required format) and timezone (original time zone and required timezone) will give String as output. you can convert String to date by using SimpleDateFormatter or also use parse method of the ZoneDateTime/Instant class.
To convert String to date:
To convert date to String: