我想将此 GMT 时间戳转换为 GMT+13:
2011-10-06 03:35:05
我尝试了大约 100 种不同的 DateFormat、TimeZone、Date、GregorianCalendar 等组合来尝试完成这项非常基本的任务。
这段代码做了我想要的当前时间:
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
String newZealandTime = formatter.format(calendar.getTime());
但我想要的是设置时间而不是使用当前时间。
我发现每当我尝试像这样设置时间时:
calendar.setTime(new Date(1317816735000L));
使用本地计算机的时区。这是为什么?我知道当“new Date()”返回 UTC+0 时间时,为什么当您以毫秒为单位设置时间时,它不再假定时间是 UTC 时间?
是否可以:
- 设置对象上的时间(日历/日期/时间戳)
- (可能) 设置初始时间戳的时区 (calendar.setTimeZone(...))
- 使用新的时区 (formatter. setTimeZone(...)))
- 返回具有新时区时间的字符串。 (格式化程序.format(日历.getTime()))
I want to convert this GMT time stamp to GMT+13:
2011-10-06 03:35:05
I have tried about 100 different combinations of DateFormat, TimeZone, Date, GregorianCalendar etc. to try to do this VERY basic task.
This code does what I want for the CURRENT TIME:
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
String newZealandTime = formatter.format(calendar.getTime());
But what I want is to set the time rather than using the current time.
I found that anytime I try to set the time like this:
calendar.setTime(new Date(1317816735000L));
the local machine's TimeZone is used. Why is that? I know that when "new Date()" returns UTC+0 time so why when you set the Time in milliseconds does it no longer assume the time is in UTC?
Is it possible to:
- Set the time on an object (Calendar/Date/TimeStamp)
- (Possibly) Set the TimeZone of the initial time stamp (calendar.setTimeZone(...))
- Format the time stamp with a new TimeZone (formatter.setTimeZone(...)))
- Return a string with new time zone time. (formatter.format(calendar.getTime()))
发布评论
评论(15)
对我来说,最简单的方法是:
For me, the simplest way to do that is:
了解计算机时间的工作原理非常重要。话虽如此,我同意如果创建一个 API 来帮助您像实时一样处理计算机时间,那么它应该以允许您像实时一样对待它的方式工作。大多数情况都是如此,但有一些重大疏忽确实需要引起注意。
无论如何我离题了!如果您有 UTC 偏移量(使用 UTC 比 GMT 偏移量更好),您可以计算以毫秒为单位的时间并将其添加到时间戳中。请注意,SQL 时间戳可能与 Java 时间戳不同,因为计算从纪元开始的时间的方式并不总是相同 - 取决于数据库技术和操作系统。
我建议你使用 System.currentTimeMillis() 作为你的时间戳,因为这些可以在 java 中更一致地处理,而不必担心将 SQL 时间戳转换为 java Date 对象等。
要计算你的偏移量,你可以尝试这样的事情:
我希望这样有帮助!
Understanding how computer time works is very important. With that said I agree that if an API is created to help you process computer time like real time then it should work in such a way that allows you to treat it like real time. For the most part this is the case but there are some major oversights which do need attention.
Anyway I digress!! If you have your UTC offset (better to work in UTC than GMT offsets) you can calculate the time in milliseconds and add that to your timestamp. Note that an SQL Timestamp may vary from a Java timestamp as the way the elapse from the epoch is calculated is not always the same - dependant on database technologies and also operating systems.
I would advise you to use System.currentTimeMillis() as your time stamps as these can be processed more consistently in java without worrying about converting SQL Timestamps to java Date objects etc.
To calculate your offset you can try something like this:
I hope this is helpful!
tl;dr
…还有…
java.time
问题和大多数答案都使用来自最早版本的 Java 的过时的遗留日期时间类。事实证明,这些旧类很麻烦且令人困惑。避开他们。而是使用 java.time 类。
ISO 8601
您的输入字符串几乎采用标准 ISO 8601 格式。只需将中间的空格替换为
T
即可。LocalDateTime
现在解析为 < code>LocalDateTime 因为输入缺少有关 UTC 或时区偏移量的任何信息。
LocalDateTime
没有偏移量和时区的概念,因此它不代表时间轴上的实际时刻。ZoneOffset
您似乎是在说,从业务上下文来看,您知道该字符串的目的是表示比 UTC 早 13 小时的时刻。因此我们实例化一个
ZoneOffset
< /a>.OffsetDateTime
应用它来获取
OffsetDateTime
对象。这成为时间线上的一个实际时刻。ZoneId
但是你提到了新西兰。所以您心里有一个特定的时区。时区是相对于 UTC 的偏移量加上一组用于处理夏令时 (DST) 等异常情况的规则。因此,我们可以将
ZoneId
指定为ZonedDateTime
而不仅仅是偏移量。指定正确的时区名称。切勿使用 3-4 个字母的缩写,例如
EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。例如,太平洋/奥克兰
。ZonedDateTime
应用
ZoneId
。您可以轻松地调整到时间线上同一时刻的另一个区域。
从纪元开始计数
我强烈建议不要将日期时间值作为从纪元开始的计数来处理,例如从 1970 UTC 开始的毫秒数。但如果必须的话,请根据这样的数字创建一个
Instant
。然后根据需要指定一个时区(如上所示)以远离 UTC。
您的
1_317_816_735_000L
值为:2011-10-05T12:12:15Z
(2011 年 10 月 5 日星期三 12:12:15 GMT)2011-10-06T01:12:15+13:00[太平洋/奥克兰]
(2011 年 10 月 6 日星期四 01:12:15,新西兰奥克兰)。生成字符串
要生成标准 ISO 8601 格式的字符串,只需调用
toString
。请注意,ZonedDateTime 通过在方括号中附加时区名称来明智地扩展了标准格式。对于其他格式,请在 Stack Overflow 中搜索
DateTimeFormatter
类。已经覆盖很多次了。指定
FormatStyle
< /a> 和Locale
。请注意,时区与区域设置无关。您可以用日语和日语显示
Europe/Paris
日期时间。文化规范,或以葡萄牙语和巴西文化规范显示的Asia/Kolkata
日期时间。关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,例如 java.util.Date、.Calendar 和 & 。
java.text.SimpleDateFormat
。Joda-Time 项目,现位于 维护模式,建议迁移到 java.time。
要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。
许多 java.time 功能都向后移植到 Java 6 和 Java 6。 ThreeTen-Backport 中的 7 并进一步适应 Android 在 ThreeTenABP(请参阅如何使用...)。
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如
Interval
、YearWeek
、YearQuarter
等。tl;dr
…also…
java.time
The Question and most Answers use outdated legacy date-time classes from the earliest versions of Java. These old classes have proven to be troublesome and confusing. Avoid them. Instead use the java.time classes.
ISO 8601
Your input string is nearly in standard ISO 8601 format. Just replace the SPACE in the middle with a
T
.LocalDateTime
Now parse as a
LocalDateTime
because the input lacks any information about offset-from-UTC or time zone. ALocalDateTime
has no concept of offset nor time zone, so it does not represent an actual moment on the timeline.ZoneOffset
You seem to be saying that from the business context you know the intention of this string is to represent a moment that is 13 hours ahead of UTC. So we instantiate a
ZoneOffset
.OffsetDateTime
Apply it to get an
OffsetDateTime
object. This becomes an actual moment on the timeline.ZoneId
But then you mention New Zealand. So you had a specific time zone in mind. A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). So we can specify a
ZoneId
to aZonedDateTime
rather than a mere offset.Specify a proper time zone name. Never use the 3-4 letter abbreviation such as
EST
orIST
as they are not true time zones, not standardized, and not even unique(!). For example,Pacific/Auckland
.ZonedDateTime
Apply the
ZoneId
.You can easily adjust into another zone for the very same moment on the timeline.
Count from epoch
I strongly recommend against handling date-time values as a count from epoch, such as milliseconds from the start of 1970 UTC. But if you must, create a
Instant
from such a number.Then assign a time zone as seen above, if desired, to move away from UTC.
Your value of
1_317_816_735_000L
is:2011-10-05T12:12:15Z
(Wed, 05 Oct 2011 12:12:15 GMT)2011-10-06T01:12:15+13:00[Pacific/Auckland]
(Thursday October 06, 2011 01:12:15 in Auckland New Zealand).Generate strings
To generate a string in standard ISO 8601 format, simply call
toString
. Note thatZonedDateTime
wisely extends the standard format by appending the name of the time zone in square brackets.For other formats, search Stack Overflow for
DateTimeFormatter
class. Already covered many times.Specify a
FormatStyle
and aLocale
.Note that time zone has nothing to do with locale. You can have a
Europe/Paris
date-time displayed in Japanese language & cultural norms, or aAsia/Kolkata
date-time displayed in Portuguese language and Brazil cultural norms.About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as
java.util.Date
,.Calendar
, &java.text.SimpleDateFormat
.The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
The ThreeTen-Extra project 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.与往常一样,我建议您阅读这篇关于 Java 中的日期和时间的文章,以便您理解它。
基本思想是,“在幕后”,一切都是自纪元以来的 UTC 毫秒内完成的。这意味着,如果您完全不使用时区进行操作,则最简单,但用户的字符串格式除外。
因此,我会跳过您建议的大部分步骤。
或者,您可以使用 Joda 时间。我听说它是一个更直观的日期时间 API。
As always, I recommend reading this article about date and time in Java so that you understand it.
The basic idea is that 'under the hood' everything is done in UTC milliseconds since the epoch. This means it is easiest if you operate without using time zones at all, with the exception of String formatting for the user.
Therefore I would skip most of the steps you have suggested.
Alternatively, you can use Joda time. I have heard it is a much more intuitive datetime API.
解决方案实际上非常简单(纯粹、简单的Java):
输出是:
The solution is actually quite simple (pure, simple Java):
OUTPUT IS:
看了一下,我认为 Java 中没有 GMT + 13 的时区。所以我认为你必须使用:(
如果有,则将“GMT”更改为该时区并删除第二行代码)
或
如果您想设置特定时间/日期,您还可以使用:
Had a look about and I don't think theres a timezone in Java that is GMT + 13. So I think you have to use:
(If there is then change "GMT" to that Timezone and remove the 2nd line of code)
OR
If you want to set a specific time/date you can also use:
我已经尝试过这段代码
并得到了这个结果
I have try this code
and getting this result
我们可以通过使用偏移值来处理这个问题
测试代码片段:
输出:
1387353270742
1387335270742
We can handle this by using offset value
Test Code snippet:
Output:
1387353270742
1387335270742
我想提供现代的答案。
您不应该真正想要将日期和时间从一个 GMT 偏移量的字符串转换为不同 GMT 偏移量和不同格式的字符串。相反,在您的程序中保留一个瞬间(时间点)作为正确的日期时间对象。仅当您需要提供字符串输出时,才将对象格式化为所需的字符串。
java.time
解析输入
对于大多数用途来说,
Instant
是存储时间点的不错选择。如果您需要明确表明日期和时间来自 GMT,请改用OffsetDateTime
。转换、格式化和打印输出
这打印了:
我指定了太平洋/奥克兰时区,而不是您提到的偏移量 +13:00。我知道您想要新西兰时间,太平洋/奥克兰更好地告诉读者这一点。时区还考虑夏令时 (DST),因此您无需在自己的代码中考虑这一点(对于大多数用途)。
由于
Oct
是英语,因此最好为格式化程序提供显式区域设置。GMT
也可能已本地化,但我认为它只是在所有语言环境中打印GMT
。格式模式字符串中的
OOOO
是打印偏移量的一种方法,这可能比打印从z
获得的时区缩写更好,因为时区缩写是常常含糊其辞。如果您需要NZDT
(新西兰夏令时),只需将z
放在那里即可。您的问题
我将回答您与 java.time 中的现代类相关的编号问题。
不,现代类是不可变的。您需要从一开始就创建一个具有所需日期和时间的对象(这有很多优点,包括线程安全)。
我在代码中使用的
atZone
方法返回具有指定时区的ZonedDateTime
。其他日期时间类也有类似的方法,有时称为 atZoneSameInstant 或其他名称。将 java.time 转换为新时区并格式化是两个不同的步骤,如图所示。
是的,转换为如图所示的所需时区和如图所示的格式。
这不是你想的那样,它很好地展示了旧类的几个(许多)设计问题。
Date
没有时区。仅当您打印它时,它的 toString 方法才会获取您的本地时区并使用它来呈现字符串。new Date()
也是如此。在过去的 25 年里,这种行为让很多很多程序员感到困惑。日历
有有一个时区。当您执行calendar.setTime(new Date(1317816735000L));
时,它不会改变。链接
Oracle 教程:日期时间 解释如何使用 java.time。
I should like to provide the modern answer.
You shouldn’t really want to convert a date and time from a string at one GMT offset to a string at a different GMT offset and with in a different format. Rather in your program keep an instant (a point in time) as a proper date-time object. Only when you need to give string output, format your object into the desired string.
java.time
Parsing input
For most purposes
Instant
is a good choice for storing a point in time. If you needed to make it explicit that the date and time came from GMT, use anOffsetDateTime
instead.Converting, formatting and printing output
This printed:
I specified time zone Pacific/Auckland rather than the offset you mentioned, +13:00. I understood that you wanted New Zealand time, and Pacific/Auckland better tells the reader this. The time zone also takes summer time (DST) into account so you don’t need to take this into account in your own code (for most purposes).
Since
Oct
is in English, it’s a good idea to give the formatter an explicit locale.GMT
might be localized too, but I think that it just printsGMT
in all locales.OOOO
in the format patterns string is one way of printing the offset, which may be a better idea than printing the time zone abbreviation you would get fromz
since time zone abbreviations are often ambiguous. If you wantNZDT
(for New Zealand Daylight Time), just putz
there instead.Your questions
I will answer your numbered questions in relation to the modern classes in java.time.
No, the modern classes are immutable. You need to create an object that has the desired date and time from the outset (this has a number of advantages including thread safety).
The
atZone
method that I use in the code returns aZonedDateTime
with the specified time zone. Other date-time classes have a similar method, sometimes calledatZoneSameInstant
or other names.With java.time converting to a new time zone and formatting are two distinct steps as shown.
Yes, convert to the desired time zone as shown and format as shown.
It’s not the way you think, which goes nicely to show just a couple of the (many) design problems with the old classes.
Date
hasn’t got a time zone. Only when you print it, itstoString
method grabs your local time zone and uses it for rendering the string. This is true fornew Date()
too. This behaviour has confused many, many programmers over the last 25 years.Calender
has got a time zone. It doesn’t change when you docalendar.setTime(new Date(1317816735000L));
.Link
Oracle tutorial: Date Time explaining how to use java.time.
显示所有时区的日期和时间
display date and time for all timezones
一种快速方法是:
输出
新日期:2015-07-02T16:51:46
A quick way is :
Output
NEW DATE: 2015-07-02T16:51:46
您的方法无需任何修改即可工作。
Your approach works without any modification.
Joda-Time
java.util.Date/Calendar 类很混乱,应该避免。
更新:Joda-Time 项目处于维护模式。该团队建议迁移到 java.time 类。
这是使用 Joda-Time 2.3 库的答案。很容易。
如示例代码中所述,我建议您尽可能使用命名时区,以便您的编程可以处理夏令时(夏令时)和其他异常情况。
如果您在字符串中间放置了一个
T
而不是空格,则可以跳过前两行代码,使用格式化程序来解析字符串。 DateTime 构造函数可以采用 < 中的字符串href="https://en.wikipedia.org/wiki/ISO_8601" rel="nofollow">ISO 8601 格式。转储这些值...
运行时...
Joda-Time
The java.util.Date/Calendar classes are a mess and should be avoided.
Update: The Joda-Time project is in maintenance mode. The team advises migration to the java.time classes.
Here's your answer using the Joda-Time 2.3 library. Very easy.
As noted in the example code, I suggest you use named time zones wherever possible so that your programming can handle Daylight Saving Time (DST) and other anomalies.
If you had placed a
T
in the middle of your string instead of a space, you could skip the first two lines of code, dealing with a formatter to parse the string. The DateTime constructor can take a string in ISO 8601 format.Dump those values…
When run…
查找具有两个不同时区
输出的 持续时间或时间间隔
周期 = P117DT13H40M
To find duration or time interval with two different time zone
output
period = P117DT13H40M