比较两个不同时区的日期对象,并以秒为单位获取确切的时差 [英] Comparing two date objects of different TimeZones and get the exact time difference in seconds

查看:80
本文介绍了比较两个不同时区的日期对象,并以秒为单位获取确切的时差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将电子邮件(日期对象)的接收日期与JSONObject中的日期(字符串)进行比较。这两个日期将属于不同的时区,相差1小时。

I am trying to compare received date of an email(date object) with a date(String) in a JSONObject. The two dates are going to be of different Timezones with a difference of 1 hour.

我的情况是,我必须以秒为单位来获得它们之间的确切差异,如果差异为+/- 10秒,我就会找到一个匹配项。为此,我决定将两者都转换为 UTC,然后进行更改。这是我的代码:

My scenario is that I'll have to get the exact difference between them in seconds and if the difference is +/- 10 seconds, I would have found a match. For this purpose, I decided to convert the both into 'UTC' and then do a difference. Here is my code:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

String MsgDtStr = sdf.format(messagesToBeProcessed.getReceivedDate()); 

Date MsgDt = sdf.parse(MsgDtStr);

Date ObjDt = sdf.parse((JsonObj.get("date").toString()));

int DiffInSecs = (int) (ObjDt.getTime() - MsgDt.getTime()) / 1000 % 60;

if (DiffInSecs >= -10 && DiffInSecs <= 10) {
                System.out.println("Found a match!");
                MatchedList.add(i);
}

这似乎给了我正确的结果。应该与json对象匹配的邮件匹配。即差异为+/- 10秒。但是,当我尝试在上述逻辑之后打印日期和 DiffInSecs 时,得到的值如下:

This seems to give me the correct result. The mails that are supposed to match with the json objects match. i.e the difference is +/- 10 seconds. However, when I try to print the dates and DiffInSecs after the above logic, I get values like this:

date in object: 2017-06-22 19:47:25
date in message: 2017-06-22 23:47:30
DiffInSecs: -5

        ........

date in object: 2017-06-22 17:50:38
date in message: 2017-06-22 21:50:39
DiffInSecs: -1

我发现两者之间存在差异间隔4小时。现在我很困惑自己的逻辑如何工作。有什么解释吗?

I see that there is a difference of 4 hours between the times. Now I am confused how my logic is even working. Any explanations on this? and is my approach to the problem even correct?

这些是我应该使用的邮件和jsonobject的示例日期值,这些值应该匹配:(如何我以任何方式实现了这一目标,而不仅仅是我发布的方法)

These are my sample date values of a mail and a jsonobject that I should work with and these should match: (How can I achieve this in any way, not just the aproach I posted)

messagesToBeProcessed [i] .getReceivedDate():Thu Jun 22 01:03 :13 CDT 2017
messagesToBeProcessed [i] .getReceivedDate()。getTime():1498111393000

Obj.get('date'):2017-06-22 02:03:03
ObjDt.getTime():1498096983000

编辑:

正如JBNizet在他的评论中指出的那样,我需要删除%60 以获取精确的秒数差异。

As pointed out by JBNizet in his comment, I'll need to remove the %60 to get the exact difference in seconds.

好的,现在我觉得坚持使用旧的API毫无意义。现在,我在消息对象中的日期不再像上面结果中发布的那样转换为UTC。我不确定为什么它会更早生效并且不再起作用(欢迎对此进行任何解释/评论)。正如Hugo在回答中指出的那样,使用新的Java.Time API更好。

Okay, now I feel sticking to the old API doesn't make sense. Now my date in the message object is not being converted to UTC anymore like I posted in the above result. I am not sure why it worked earlier and doesn't anymore (Any explanations/comments on this are welcome). As pointed out by Hugo in his answer, using new Java.Time API is better.

希望此线程可以帮助将来的人们找到路。

Hope this thread helps someone find way in the future.

推荐答案

我不确定您使用的是哪个Java版本,但无论如何:旧类( Date 日历 SimpleDateFormat )具有很多问题设计问题,并且已被新的Date / Time API取代。

I'm not sure which java version you're using, but anyway: the old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by new Date/Time APIs.

如果您使用的是 Java 8 ,请考虑使用新的java.time API 。与旧的API相比,更少的错误和更少的错误

If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.

如果您使用的是 Java< = 7 ,则可以使用 ThreeTen Backport ,它是Java 8的新日期/时间类的绝佳反向端口。对于 Android ,有 ThreeTenABP (有关如何使用它的更多信息< a href = https://stackoverflow.com/a/38922755/7605325>此处)。

If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).

下面的代码对这两种方法均适用。
唯一的区别是软件包名称(在Java 8中为 java.time ,在ThreeTen Backport(或Android的ThreeTenABP)中为 org。 threeten.bp ),但类和方法名称相同。

The code below works for both. The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.

基于 getReceivedDate()的输出,您的默认时区为 CDT
但是这些较短的时区名称如 EST CDT 含糊不清而不是标准

Based on your output for getReceivedDate(), your default timezone is CDT. But these short timezone names like EST and CDT are ambiguous and not standard.

新API使用 Continent / City 格式的长名称(由 IANA数据库。因此,
CDT 可以位于许多不同的位置,例如美国/芝加哥 America / Havana 。您必须首先检查哪个最适合您的上下文-您可以使用获取所有可用名称的列表ZoneId.getAvailableZoneIds()

The new API uses long names in the format Continent/City (used by IANA database. So, CDT can be in lots of different locations, like America/Chicago or America/Havana. You must first check which one fits best in your context - you can get a list of all available names with ZoneId.getAvailableZoneIds().

在下面的示例中,我随机选择了其中一个( America / Chicago )只是为了演示其工作原理,我使用了 DateTimeFormatter 来解析输入的 String ZoneId 将其转换为时区。

For the example below, I've picked one of them by random (America/Chicago) just to show how it works. I've used a DateTimeFormatter to parse the input String and a ZoneId to convert it to a timezone.

// parse jsonInput
String jsonInput = "2017-06-22 02:03:03";
// formatter
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// parse the input to a LocalDateTime
LocalDateTime dt = LocalDateTime.parse(jsonInput, fmt); // 2017-06-22T02:03:03
// convert it to the EDT timezone (using America/Chicago as it's currently in CDT)
ZonedDateTime z = dt.atZone(ZoneId.of("America/Chicago")); // 2017-06-22T02:03:03-05:00[America/Chicago]

// convert the java.util.Date object to the new API
Date date = new Date(1498111393000L); // using your timestamp = 2017-06-22T06:03:13 UTC
// for Java >= 8, use toInstant method
Instant instant = date.toInstant();
// for Java <= 7, use org.threeten.bp.DateTimeUtils
Instant instant = DateTimeUtils.toInstant(date);

// get the difference between them
long diffSecs = ChronoUnit.SECONDS.between(instant, z);

时差为3590秒-这是因为 2017-06-22 02 :03:03 (在我的例子中是芝加哥)等于UTC 2017-06-22T07:03 :03Z 。而您的日期(1498111393000 millis)等于UTC 2017-06-22T06:03:13Z

The difference will be 3590 seconds - that's because 2017-06-22 02:03:03 in CDT (in my example, Chicago) is equals to UTC 2017-06-22T07:03:03Z. And your date (1498111393000 millis) is equals to UTC 2017-06-22T06:03:13Z.

在您的代码,您正在使用 sdf 来解析输入 2017-06-22 02:03:03 ,但是 sdf 设置为UTC(而不是CDT),从而导致错误的结果(假设JSON输入也在CDT中)。

In your code, you're using sdf to parse the input 2017-06-22 02:03:03, but sdf is set to UTC (not to CDT), leading to incorrect results (assuming that the JSON input is in CDT as well).

如果要将JSON输入转换为UTC,可以使用 ZoneOffset.UTC 代替 ZoneId

If you want to convert the JSON input to UTC, you can use ZoneOffset.UTC instead of the ZoneId.

实际上,您必须检查输入是否确实是UTC,并相应地更改代码(上面的代码假定JSON输入在CDT中。)

Actually, you must check if the input is really in UTC or not and change the code accordingly (the code above assumes that the JSON input is in CDT).

当然,您可以对<$ c做同样的事情$ c> SimpleDateFormat

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));

Date jsonDate = sdf.parse("2017-06-22 02:03:03"); // 2017-06-22 02:03:03 in Chicago, or 2017-06-22T07:03:03 in UTC

,然后以相同的方式计算差异((jsonDate.getTime()-date.getTime())/ 1000 )。结果将与上面相同:3590秒。

And then calculate the difference the same way you're doing ((jsonDate.getTime() - date.getTime()) / 1000). The result will be the same as above: 3590 seconds.

这篇关于比较两个不同时区的日期对象,并以秒为单位获取确切的时差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆