java - Why is the time difference off when subtracting the same date from two different time zones?
问题描述
The following is an example that attempts to calculate the difference in hours between time zones.
import java.util.*;
import java.text.*;
public class ForPosting
{
public static void main (String[] args)
{
try {
String myDateString = "07-13-2021 11:00:00";
SimpleDateFormat localDateTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
SimpleDateFormat utcDateTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
localDateTime.setTimeZone(TimeZone.getTimeZone("EET"));
System.out.println(localDateTime.parse(myDateString));
utcDateTime.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(utcDateTime.parse(myDateString));
float diff = ((localDateTime.parse(myDateString).getTime() - utcDateTime.parse(myDateString).getTime() ) / 3600000);
System.out.println("EET & UTC Time Difference : " + diff);
localDateTime.setTimeZone(TimeZone.getDefault());
System.out.println(localDateTime.parse(myDateString));
utcDateTime.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(utcDateTime.parse(myDateString));
diff = ((localDateTime.parse(myDateString).getTime() - utcDateTime.parse(myDateString).getTime() ) / 3600000);
System.out.println("Default & UTC Time Difference : " + diff);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The above code generates the following output.
The Default & UTC Time Difference : 4.0
was confirmed by checking the current dates and it confirms there is a 4 hour difference.
Doing the same check for EET & UTC is different.
EET & UTC Time Difference : -3.0
The output shows a 3 hour difference yet the following shows there is only 2.
Why does the EET & UTC actual time show 2 hour difference yet the Java code shows a 3 hour difference?
解决方案
EET is not a time zone
EET is a common abbreviation of some 20 time zones in Europe and Northern Africa that are at offset +02:00 from UTC during standard time. Many, not all of them are using summer time (daylight saving time) abbreviated EEST for Eastern European Summer Time and hence are at offset +03:00 during the 7 “summer” months. So what you get when asking for EET
, I can’t tell. So don’t do that. Use a proper time zone ID like Europe/Uzhgorod, always in region/city format. So that you know what you get.
So to answer your question:
Why does the EET & UTC actual time show 2 hour difference yet the Java code shows a 3 hour difference?
Because they interpret EET differently. Both interpretations are fully valid and none is authoritative.
This is nothing special for EET. Many two, three, four and five letter time zone abbreviations are in common use. Very many of them are ambiguous, like EET. And very many of them are not time zones. It may be that there are situations where you can use one for informal communication to the user, for example just to distinguish between EET and EEST in a situation where the user knows well enough what each of those means in the context. You certainly cannot rely on them for defining a time zone in your program.
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work. To find the difference between some time zone and UTC at a moment in time:
ZoneId zone = ZoneId.of("Europe/Uzhgorod");
Instant when = Instant.now();
ZoneOffset differenceFromUtc = when.atZone(zone).getOffset();
System.out.format("%s & UTC Time Difference : %s%n", zone, differenceFromUtc);
Output when running just now:
Europe/Uzhgorod & UTC Time Difference : +03:00
It’s summer now in Europe/Uzhgorod, and the difference of 3 hours comes from that time zone using summer time. Try with an instant in winter:
Instant when = Instant.parse("2022-01-01T00:00:00Z");
Europe/Uzhgorod & UTC Time Difference : +02:00
As I said, some Eastern European time zones do not use summer time. Try with one of those:
ZoneId zone = ZoneId.of("Europe/Kaliningrad");
Instant when = Instant.now();
Europe/Kaliningrad & UTC Time Difference : +02:00
Minor comments to your code
While UTC
works for defining a time zone, the canonical ID is Etc/UTC
. Etc is a pseudo-region for time zones that don’t belong in a well-defined geographical region including Etc/UTC
, Etc/GMT
and also the IDs for mere whole-hour offsets like Etc/GMT-2
(for offset +02:00, the sign is inverted).
Assigning the result of your division to a float
does not help you. You are dividing a long
values by an int
value, and the result is always truncated to an long
number. When assigning to a float
you will still always have a whole number. If you wanted a fraction as result, you would need to convert at least one of the operands to float
(or double
) before dividing.
And a funny detail, your code measures the difference in hours between when it’s 11 o’clock in EET and 11 o’clock in UTC. You get a result exactly because there are 3 hours between those two moments. What I am not so pleased about is that you are not measuring the difference at a well-defined point in time. Instead in my code I am choosing one point in time and finding the difference at that point.
Link
Oracle tutorial: Date Time explaining how to use java.time.
推荐阅读
- python - Pygame 的大多数关键输入都不起作用,例如(w、a、s、d)。只有箭头键似乎在工作
- scala - 在 Spark 集群中分发 FlatMap
- python - 使用 OCR python 从屏幕读取文本
- c# - C# 字符串不替换制表符
- linux - 如何将压缩的 zip 目录拆分为单个文件?
- reactjs - 在 react.js 中访问实时 firebase 对象
- ruby - Selenium ChromeDriver 版本冲突
- html - Qualtrics - 冻结并排问题的第一列和第一行,以便使用 position -webkit-sticky 更好地滚动
- html - 如何在 HTML 中翻转卡片
- linux - 空环境变量名