英文:
Different time conversion by using java.util.Date in Java
问题
以下是翻译好的部分:
我正在使用以下代码,通过在Java中使用java.util.Date
类进行从时代到时间的转换。
Long scheduledTime = 1602258300000L;
Date date = new Date(scheduledTime);
System.out.println("Date obj :" + date);
在两个不同的时区服务器上运行相同代码时,以下是输出:
在东部夏令时(EDT)服务器上 -
Date obj :Fri Oct 09 11:45:00 EDT 2020
在印度标准时间(IST)服务器上 -
Date obj :Fri Oct 09 21:15:00 IST 2020
为什么会发生这种情况?我只传递了毫秒。这些数据应该在所有服务器上都被视为21:15。为什么Date类会改变数据?
请分享一段示例代码,以获取与服务器的时区无关的相同时间数据。
英文:
I am using the below code for epoch to time conversion by using java.util.Date
class in Java.
Long scheduledTime = 1602258300000L;
Date date = new Date(scheduledTime);
System.out.println("Date obj :" + date);
Below are the outputs while running the same code on two different timezone server :
On EDT server-
Date obj :Fri Oct 09 11:45:00 EDT 2020
On IST server -
Date obj :Fri Oct 09 21:15:00 IST 2020
Why does this happen? I am only passing milliseconds. This data is supposed to be treated as 21:15 on all servers. Why does Date class change the data?
Please share a sample piece of code for getting the same time data regardless of the timezone of the server.
答案1
得分: 11
A Date
object represents a specific instant in time, represented by a given number of milliseconds since the Unix epoch.
The toString()
method converts that instant in time into a local time based on the default time zone. It's not that the Date
value itself "has" a time zone - it's just toString()
that uses the default one.
> This data is supposed to be treated as 21:15 on all servers.
That suggests you want to use the Indian time zone in all servers, at least when converting the instant in time for display. Without knowing anything more about your application, that's all we can say... other than "don't use java.util.Date
or java.util.Calendar
; use the java.time
classes instead". They're much better designed, and you're less likely to run into problems like this.
英文:
A Date
object represents a specific instant in time, represented by a given number of milliseconds since the Unix epoch.
The toString()
method converts that instant in time into a local time based on the default time zone. It's not that the Date
value itself "has" a time zone - it's just toString()
that uses the default one.
> This data is supposed to be treated as 21:15 on all servers.
That suggests you want to use the Indian time zone in all servers, at least when converting the instant in time for display. Without knowing anything more about your application, that's all we can say... other than "don't use java.util.Date
or java.util.Calendar
; use the java.time
classes instead". They're much better designed, and you're less likely to run into problems like this.
答案2
得分: 4
java.time
我建议您使用现代的 Java 日期和时间 API,即 java.time
,来处理您的日期和时间工作。
long scheduledTime = 1_602_258_300_000L;
Instant pointInTime = Instant.ofEpochMilli(scheduledTime);
System.out.println(pointInTime);
这段代码的输出将在所有服务器和所有时区中都相同:
> 2020-10-09T15:45:00Z
由于您想要 21:15,需要指定印度的时区:
ZoneId serverTimeZone = ZoneId.of("Asia/Kolkata");
ZonedDateTime dateTime = pointInTime.atZone(serverTimeZone);
System.out.println(dateTime);
这段代码的输出将是:
> 2020-10-09T21:15+05:30[Asia/Kolkata]
发生了什么问题?
纪元是一个与时区无关的时间点。因此,毫秒数也表示一个时间点。在您的情况下,那个时间点是 2020 年 10 月 9 日星期五 15:45:00 UTC。在那个时间点,印度的时间是 21:15,在北美东海岸是 11:45。过时的 Date
类有一个令人困惑的特点:一方面,它只表示一个时间点;另一方面,它的 toString
方法获取了 JVM 的时区设置,并将其用于呈现要返回的字符串,从而让您错误地认为在不同的时区中会得到不同的 Date
对象,但实际上它们是相等的。
链接
- Oracle 教程:日期时间 解释了如何使用
java.time
。 - 纪元和 Unix 时间戳转换工具 可以帮助您查找您的毫秒数在 UTC/GMT 和您所在时区中的等效时间。
英文:
java.time
I recommend you use java.time, the modern Java date and time API, for your date and time work.
long scheduledTime = 1_602_258_300_000L;
Instant pointInTime = Instant.ofEpochMilli(scheduledTime);
System.out.println(pointInTime);
Output from this snippet will be the same on all servers in all time zones:
> 2020-10-09T15:45:00Z
Since you want 21:15, specify the time zone for India:
ZoneId serverTimeZone = ZoneId.of("Asia/Kolkata");
ZonedDateTime dateTime = pointInTime.atZone(serverTimeZone);
System.out.println(dateTime);
> 2020-10-09T21:15+05:30[Asia/Kolkata]
What went wrong?
The epoch is one point in time independent of time zone. so a count of milliseconds also denotes one point in time. In your case that point in time is Friday 9. October 2020 15:45:00 UTC. And at that point in time it was 21:15 in India and 11:45 on the East coast of North America. It’s a confusing trait of the outdated Date
class that on one hand it represents just a point in time, on the other hand its toString
method grabs the time zone setting of the JVM and uses it for rendering the string to be returned, thus giving you the false impression that you get different Date
objects in different time zones when in fact they are equal.
Links
- Oracle tutorial: Date Time explaining how to use java.time.
- Epoch & Unix Timestamp Conversion Tools where you can check what’s the equivalent of your milliseconds in UTC/GMT and in your own time zone.
答案3
得分: 1
// 引用其他人的建议,你现在应该使用 `java.time` 包来处理时间。如果你查看 `java.util.Date` 的 `toString()` 方法的文档,它会将 Date 对象转换为以下形式的字符串:
// >EEE MMM d m dd hh:mm:ss zzz yyyy
// 就像以下代码在后台运行一样:
public String toString(){
Date date=this;
SimpleDateFormat simpleDateFormat=new SimpleDateFormat(
"EEE MMM d m dd hh:mm:ss zzz yyyy");
simpleDateFormat.setTimeZone(TimeZone.getDefault()); // 这一行很重要。
return simpleDateFormat.format(date);
}
// 现在,如果你想要为特定时区格式化你的 Date 对象,你可以做同样的操作,包括设置时区:
Long scheduledTime = 1602258300000L;
Date date = new Date(scheduledTime);
SimpleDateFormat simpleDateFormat=new SimpleDateFormat(
"EEE MMM d m dd hh:mm:ss zzz yyyy");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("IST"));
String dateStr = simpleDateFormat.format(date);
System.out.println("Date obj :" + dateStr);
英文:
As pointed by others you should now use the java.time
package for working with time. If you look at the documentation of the toString()
method of java.util.Date
, it says that it coverts the Date object to a String of form:
>EEE MMM d m dd hh:mm:ss zzz yyyy
It is like the following code is running in the background:
public String toString(){
Date date=this;
SimpleDateFormat simpleDateFormat=new SimpleDateFormat(
"EEE MMM d m dd hh:mm:ss zzz yyyy");
simpleDateFormat.setTimeZone(TimeZone.getDefault()); //This line is important.
return simpleDateFormat.format(date);
}
Now, if you wanna format your Date object for a certain timezone you can do the same including setting the timezone:
Long scheduledTime = 1602258300000L;
Date date = new Date(scheduledTime);
SimpleDateFormat simpleDateFormat=new SimpleDateFormat(
"EEE MMM d m dd hh:mm:ss zzz yyyy");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("IST"));
String dateStr = simpleDateFormat.format(date);
System.out.println("Date obj :" + dateStr);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论