Java 使用基于时区的时间戳创建UTC日期

Java 使用基于时区的时间戳创建UTC日期,java,facebook,date,timezone,Java,Facebook,Date,Timezone,奇怪的问题,但你必须首先知道,Facebook API定义了所有日期,时间戳long=秒数,始于1970年1月1日00:00:00,位于PDT时区Pacifica time。 此秒数不是UTC时间戳,而是基于非标准位置的假时间戳 在java中有没有一种简单的方法可以将这个长时间戳转换成我可以使用的普通日期对象,并使用标准日期格式化程序以法语格式打印 PS:这不仅仅是一个+7小时的问题,夏令时也包括在这个时间戳中。此外,我们在法国也有夏令时,但不是同样的夏令时 谢谢 更新: 更复杂的是,只有一个固

奇怪的问题,但你必须首先知道,Facebook API定义了所有日期,时间戳long=秒数,始于1970年1月1日00:00:00,位于PDT时区Pacifica time。 此秒数不是UTC时间戳,而是基于非标准位置的假时间戳

在java中有没有一种简单的方法可以将这个长时间戳转换成我可以使用的普通日期对象,并使用标准日期格式化程序以法语格式打印

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

谢谢

更新: 更复杂的是,只有一个固定的delta。 我认为Facebook将我给出的日期记录为PSD日期。如果我记录26/10/2011星期四16H00巴黎时区,脸谱网记录26/10/2011 16H00旧金山时区,并将其转换为适当的第二UTC自1970以来。问题在于,这种转换考虑了旧金山的日光节约。 我做了以下基准测试来证明这一点:

2011年12月31日16:00-法国时间FB时间戳=1325376000而不是1325343600时间戳UTC->增量:-32400 2012年7月31日16:00-法国时间FB Timestamp=1343775600而非1343743200->增量:-32400 2012年10月3日16:00-法国时间FB Timestamp=1349305200而非1349272800->增量:-32400 2012年10月28日08:00-法国时间FB时间戳=1351436400而不是1351407600->增量:-28800 2012年3月25日08:00-法国时间FB时间戳=1332687600而不是1332655200->增量:-32400 2012年3月24日23:30-法国时间FB Timestamp=1332657000而非1332668200->增量:-28800 2012年10月27日23:30-法国时间FB时间戳=1351405800而不是1351373400->增量:-32400
事实上,我需要一种方法将2011年10月31日16H00 PDT转换为2011年10月31日16H00 Paris TZ…

创建SimpleDataFormat时,可以指定时区。它生成的日期为GMT+0。通过在时区中使用另一个SimpleDataFormat,可以在本地时区中显示它。或者你也可以用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);
}

由于格林尼治标准时间没有夏令时的变化,这是一个很好的通用时间

那么facebook与标准epoch相比有+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-01-01 00:00:00 UTC以来的秒数不会改变

更新:所以你给脸谱网一个存储的日期,你真正的问题是你不能给它一个合适的时区,所以它存储在旧金山的任何时间。在存储之前,您可以将时间转换为美国/洛杉矶时区。或者,您可以在检索后将其转换回,如下所示:

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)));    
} 

我编辑了我的问题。我所说的时间戳是指自1970年1月1日以来的秒数,但不是UTC 1970年1月1日,即太平洋一区。