【问题标题】:Time Difference of two different timezone两个不同时区的时差
【发布时间】:2017-06-30 04:11:09
【问题描述】:

我想获取当前时间(即 IST)和存储在 DB(EST) 中的时间的差异。为此,我试图在计算差异之前将当前时间转换为 EST。但它不起作用。在以下方法中, 本地时间不会仅转换为 EST。你能建议我更好的方法吗? getModifiedDate的返回类型是java.sql.Timestamp,数据类型 该栏目为DATE

代码:

Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("EST"));
 cal.setTimeInMillis(System.currentTimeMillis());
 cal.getTimeInMillis() - emp.getModifiedDate().getTime();

我试图使用 SimpleDateFormat 来做,但我不确定如何继续使用这种方法。

如果你能提供有帮助的代码sn-p

【问题讨论】:

  • “emp”从何而来?
  • emp是映射到表的实体类Employee的obj引用
  • emp.getModifiedDate().getTime(); 的输出是什么?
  • 您遇到的问题是毫秒是同一时间,因为它是基于 UTC 的。时区为 UTC 时间提供了本地视图。
  • 我不认为我理解任何转换的必要性。 Timestamp 只是一个时间点,在所有时区都是一样的。如果您可以告诉我们您的数据库列的数据类型,并给我们一个示例值和该值的请求结果(在以色列标准时间的某个时间点),我们可能会为您提供更好的帮助(哎呀,IST 是爱尔兰夏令时间?印度标准时间?这三个字母的缩写非常危险且令人困惑)。

标签: java timezone datetime-conversion


【解决方案1】:

你可以试试 java.util.TimeZone

    long now = System.currentTimeMillis();
    long diff = TimeZone.getTimeZone("IST").getOffset(now) - TimeZone.getTimeZone("EST").getOffset(now); 

getOffset - 返回该时区在指定日期与 UTC 的偏移量

【讨论】:

  • 它返回 10.5 小时但实际差异是 9.5 小时
  • 使用 getOffset(System.currentTimeMillis()) 代替 getRawOffset() 来考虑 DST 调整。
【解决方案2】:

如果您可以访问 Java 8,那么直接计算两个日期之间的差异可能同样容易,而不是先调整到目标时区。

您可以使用java.time 包中的ZonedDateTime 执行此操作:

// Our timestamp
Timestamp ts = emp.getModifiedDate();

// Convert timestamp to ZonedDateTime in the correct time zone
ZonedDateTime estTime = ts.toLocalDateTime().atZone(ZoneId.of("America/New_York"));

// Could pass in ZoneId.of("Asia/Kolkata") argument to now(...), but not required
// as "now" is the same instant in all time zones.
ZonedDateTime zonedNow = ZonedDateTime.now();

// Can use other ChronoUnit values if required.
long timeDiff = ChronoUnit.MILLIS.between(zonedNow, estTime);

// Use timeDiff as required

【讨论】:

    【解决方案3】:

    我建议使用JDK 8java.time API,这在很大程度上简化了这一点。考虑以下示例:

    Timestamp t = emp.getModifiedDate();
    Duration.between(t.toInstant(), ZonedDateTime.now(ZoneId.of("Asia/Kolkata")).toInstant());
    

    从 DB 中检索到的时间戳已转换为 UTC 中的 Instant,同样Asia/Kolkata 区域中的当前时间已转换为 Instant,并计算了两者之间的 Duration。您可以从持续时间中检索所需的信息。

    【讨论】:

    • 感谢您的帮助 Pallavi 但目前我们使用的是 java 1.5
    • 1.5,那是旧的,@Rehman。现在大约12岁。如果你有机会升级到 Java 6(或更高版本),你可以使用ThreeTen Backport 和上面的代码。这是一个很好的答案。
    【解决方案4】:

    您可以使用java.time.Duration 找到它,它以ISO-8601 standards 为模型,并作为JSR-310 implementation 的一部分与Java-8 一起引入。 Java-9 引入了一些更方便的方法。

    import java.time.Duration;
    import java.time.LocalDate;
    import java.time.OffsetDateTime;
    import java.time.ZoneId;
    import java.time.ZoneOffset;
    
    public class Main {
    
        public static void main(String[] args) {
            // Test
            System.out.println(formatDuration(diffBetweenTimeZones("Asia/Kolkata", "America/New_York")));
            System.out.println(formatDuration(diffBetweenTimeZones("America/New_York", "Asia/Kolkata")));
    
            // You can use the returned value to get the ZoneOffset which you can use for
            // other processing e.g.
            ZoneOffset offset = ZoneOffset.of(formatDuration(diffBetweenTimeZones("Asia/Kolkata", "America/New_York")));
            System.out.println(offset);
            System.out.println(OffsetDateTime.now(offset));
        }
    
        static Duration diffBetweenTimeZones(String tz1, String tz2) {
            LocalDate today = LocalDate.now();
            return Duration.between(today.atStartOfDay(ZoneId.of(tz1)), today.atStartOfDay(ZoneId.of(tz2)));
        }
    
        static String formatDuration(Duration duration) {
            long hours = duration.toHours();
            long minutes = duration.toMinutes() % 60;
            String symbol = hours < 0 || minutes < 0 ? "-" : "+";
            return String.format(symbol + "%02d:%02d", Math.abs(hours), Math.abs(minutes));
    
            // ####################################Java-9####################################
            // return String.format(symbol + "%02d:%02d", Math.abs(duration.toHoursPart()),
            // Math.abs(duration.toMinutesPart()));
            // ####################################Java-9####################################
        }
    }
    

    输出:

    +09:30
    -09:30
    +09:30
    2021-03-24T19:52:29.474858+09:30
    

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    请注意,java.util 日期时间 API 已过时且容易出错。建议彻底停止使用,改用modern date-time API*


    * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      【解决方案5】:

      TimeZone 有两个方法 getRawOffetgetOffset 检索时区与 UTC 的偏移(以毫秒为单位)。第二个是针对夏令时调整的,请求日期检查是否生效。

      TimeZone current = TimeZone.getDefault();
      TimeZone db = TimeZone.getTimeZone("US/Eastern");  // or "EST5EDT", or "America/New_York"
      System.out.printf("DB: %s    Current: %s\n", db, current);
      
      System.out.printf("Raw: %.1f h\n", (db.getRawOffset() - current.getRawOffset())/3_600_000D);
      
      final long now = System.currentTimeMillis();
      System.out.printf("DST: %.1f h\n", (db.getOffset(now) - current.getOffset(now))/3_600_000D);
      

      【讨论】:

      • 感谢您的回复卡洛斯。但是对于 getOffset() 和 getRawOffset() ,差异返回为 10.5 小时,而 IST 和 EST 之间的实际差异是 9.5 小时
      • 这是预期的,Wikipedia EST 是 UTC-05 并且 IST 是 UTC+5:30 - 问题是 EST 不包括夏令时,这将是 EDT,正确的应该是 EST5EDT,对于这两种情况。但不推荐使用此类缩写的文档,最好使用“US/Eastern”或“America/New_York”这样的 ID。
      • 更改了答案以反映这一点并以小时而不是毫秒给出结果
      猜你喜欢
      • 2021-06-20
      • 2021-09-22
      • 1970-01-01
      • 2018-02-26
      • 2015-12-22
      • 2016-08-16
      • 2017-12-18
      • 1970-01-01
      • 2017-06-16
      相关资源
      最近更新 更多