【问题标题】:Create a Date UTC with a timezone-based timestamp使用基于时区的时间戳创建 Date UTC
【发布时间】:2011-12-01 12:29:43
【问题描述】:

奇怪的问题,但您必须首先知道 Facebook API 定义了所有带有时间戳的日期(long = 秒数)开始于 01/01/1970 00 :00:00 位于 PDT 时区(太平洋时间)。 这个秒数不是 UTC 时间戳,而是基于非标准位置的虚假时间戳。

在 java 中是否有一种简单的方法可以将此长时间戳转换为我可以使用的普通 Date 对象(并使用标准日期格式化程序以法语格式打印)?

PS:这不仅仅是一个 +7 小时的问题,夏令时包含在这个时间戳中。此外,我们在法国也有夏令时,但不一样......

谢谢

更新: 它比一个固定的增量更复杂。 我认为 Facebook 会将我提供的日期记录为 PSD 日期。如果我记录 2011 年 10 月 26 日星期四 16H00(巴黎时区),Facebook 记录 2011 年 10 月 26 日 16H00(旧金山时区)并将其转换为自 1970 年以来适当的第二个 UTC。问题是这种转换考虑了旧金山的夏令时。 我做了以下基准来证明它:

  • (2011 年 12 月 31 日 16:00 - 法国时间)FB 时间戳 = 1325376000 而不是 1325343600(UTC 时间戳)-> 增量:-32400
  • (2012 年 7 月 31 日 16:00 - 法国时间)FB 时间戳 = 1343775600 而不是 1343743200 -> 增量:-32400
  • (03/10/2012 16:00 - 法国时间)FB 时间戳 = 1349305200 而不是 1349272800 -> Delta : -32400
  • (28/10/2012 08:00 - 法国时间)FB 时间戳 = 1351436400 而不是 1351407600 -> Delta : -28800
  • (25/03/2012 08:00 - 法国时间)FB 时间戳 = 1332687600 而不是 1332655200 -> Delta : -32400
  • (24/03/2012 23:30 - 法国时间)FB 时间戳 = 1332657000 而不是 1332628200 -> Delta : -28800
  • (27/10/2012 23:30 - 法国时间)FB 时间戳 = 1351405800 而不是 1351373400 -> Delta : -32400

事实上,我需要一种方法将 31/10/2011 16H00 (PDT) 转换为 31/10/2011 16H00 (Paris TZ)...

【问题讨论】:

    标签: java facebook date timezone


    【解决方案1】:

    创建 SimpleDateFormat 时,您可以指定时区。它产生的日期是 GMT+0。您可以通过在您的时区使用另一个 SimpleDateFormat 来在您的本地时区显示它。 (或者你可以使用 JodaTime 来做同样的事情)

    如果您需要太平洋标准时间 (PST) 时区自 1970 年 1 月 1 日以来的毫秒数,您可以这样做

    public static final long PST_1970; static {
        try {
            final SimpleDateFormat MM_DD_YYYY = new SimpleDateFormat("MM/dd/yyyy");
            MM_DD_YYYY.setTimeZone(TimeZone.getTimeZone("PST"));
            PST_1970 = MM_DD_YYYY.parse("01/01/1970").getTime();
        } catch (ParseException e) {
            throw new AssertionError(e);
        }
    }
    
    public static void main(String... args) throws InterruptedException {
        long now = System.currentTimeMillis();
        long timeSincePST = now - PST_1970;
        System.out.println("now since 1970 GMT " + now);
        System.out.println("millis since 1970 PST " + timeSincePST);
    }
    

    由于 GMT 没有夏令时变化,因此这是一个很好的通用时间。

    【讨论】:

    • 我编辑了我的问题。通过时间戳,我的意思是“自 1970 年 1 月 1 日以来的秒数,但不是 UTC 01/01/1970,太平洋地区的秒数”。
    【解决方案2】:

    那么与标准时代相比,facebook 的固定偏移量为 +7 小时?解析时间戳时不能只减去该偏移量吗?例如:

    @Test
    public void testFacebook() throws Exception {
      long SEVEN_HRS_IN_MILLIS = 25200000;
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
      TimeZone cet = TimeZone.getTimeZone("Europe/Paris");
      df.setTimeZone(cet);
      long facebookTimestamp = 1322769308471L;
      Date then = new Date();
      then.setTime(facebookTimestamp - SEVEN_HRS_IN_MILLIS);
      assertEquals("2011-12-01 13:55:08 +0100", df.format(then));
    }
    

    请注意,时间戳通常被定义为“自引用以来的(毫秒)秒数”,这永远不能包括夏令时。如果您移动时钟上的指针,则自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数不会改变。

    更新:所以你给 facebook 一个日期来存储,你真正的问题是你不能给那个适当的时区,所以它被存储为旧金山的任何时间?您可以在存储之前将时间转换为“America/Los_Angeles”时区。或者,您可以在检索后将其转换回来,如下所示:

    private DateFormat getDateFormat(String timezone) {
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      TimeZone tz = TimeZone.getTimeZone(timezone);
      df.setTimeZone(tz);
      return df;
    }
    
    private Date getDateWithCorrectedOffset(long timestamp, DateFormat source, DateFormat target) throws ParseException {
      Date d = new Date(timestamp);
      return target.parse(source.format(d));
    }
    
    @Test
    public void testFacebook() throws ParseException {
      DateFormat parisTime = getDateFormat("Europe/Paris");
      DateFormat sfTime = getDateFormat("America/Los_Angeles");
      assertEquals("2011-12-31 16:00:00", parisTime.format(getDateWithCorrectedOffset(1325376000000L, sfTime, parisTime)));
      assertEquals("2012-07-31 16:00:00", parisTime.format(getDateWithCorrectedOffset(1343775600000L, sfTime, parisTime)));
      assertEquals("2012-10-03 16:00:00", parisTime.format(getDateWithCorrectedOffset(1349305200000L, sfTime, parisTime)));
      assertEquals("2012-10-28 08:00:00", parisTime.format(getDateWithCorrectedOffset(1351436400000L, sfTime, parisTime)));
      assertEquals("2012-03-25 08:00:00", parisTime.format(getDateWithCorrectedOffset(1332687600000L, sfTime, parisTime)));
      assertEquals("2012-03-24 23:30:00", parisTime.format(getDateWithCorrectedOffset(1332657000000L, sfTime, parisTime)));
      assertEquals("2012-10-27 23:30:00", parisTime.format(getDateWithCorrectedOffset(1351405800000L, sfTime, parisTime)));    
    } 
    

    【讨论】:

      猜你喜欢
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      • 2017-06-24
      • 2019-03-09
      • 2013-06-30
      相关资源
      最近更新 更多