Create a Date UTC with a timezone-based timestamp

Odd question, but you have to know first that Facebook API defines all the dates with a timestamp (long = number of second) started 01/01/1970 00:00:00 located on PDT timezone (Pacifica time). This number of second is not a UTC timestamp but a fake one based on a non-standard location.

Is there a simple way in java to convert this long timestamp to a normal Date object I could use (and print in french format with standard date formaters) ?

PS : It is not just a +7 hours question, daylight savings are included in this timestamp. In addition, we have also daylight saving in France but not the same ones...


UPDATE : It is more complicated that just à fixed delta. I think Facebook records the date I give as a PSD date. If I record Thursday 26/10/2011 16H00 (Paris Timezone), Facebook records 26/10/2011 16H00 (San Francisco Timezone) and converts it to the appropriate number of second UTC since 1970. The problem is that this convertion takes into account daylight savings in San Francisco. I did the following benchmark to demonstrate it :

  • (31/12/2011 16:00 - France Time) FB Timestamp = 1325376000 instead of 1325343600 (Timestamp UTC) -> Delta : -32400
  • (31/07/2012 16:00 - France Time) FB Timestamp = 1343775600 instead of 1343743200 -> Delta : -32400
  • (03/10/2012 16:00 - France Time) FB Timestamp = 1349305200 instead of 1349272800 -> Delta : -32400
  • (28/10/2012 08:00 - France Time) FB Timestamp = 1351436400 instead of 1351407600 -> Delta : -28800
  • (25/03/2012 08:00 - France Time) FB Timestamp = 1332687600 instead of 1332655200 -> Delta : -32400
  • (24/03/2012 23:30 - France Time) FB Timestamp = 1332657000 instead of 1332628200 -> Delta : -28800
  • (27/10/2012 23:30 - France Time) FB Timestamp = 1351405800 instead of 1351373400 -> Delta : -32400

In fact I need a way to convert 31/10/2011 16H00 (PDT) to 31/10/2011 16H00 (Paris TZ)...


When you create the SimpleDateFormat you can specify the timezone. The Date it produced is GMT+0. You can display it in your local timezone by using another SimpleDateFormat with your timezone. (Or you could use JodaTime to do the same)

If you need the number of milli-seconds since 1/1/1970 in the PST timezone you can do

public static final long PST_1970; static {
    try {
        final SimpleDateFormat MM_DD_YYYY = new SimpleDateFormat("MM/dd/yyyy");
        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);

As GMT doesn't have daylight savings changes it is a good general time to use.

So facebook have a fixed offset of +7 hours compared to standard epoch? Can't you just subtract that offset when you parse a timestamp? For example:

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

Note that timestamp is usually defined as "number of (milli)seconds since a reference", and this can never include daylight savings time. The number of seconds since 1970-01-01 00:00:00 UTC does not change if you move the hands on your clock.

UPDATE: So you're giving facebook a date to store, and your real problem is that you can't give that a proper time zone, so it gets stored as whatever time it is in San Francisco? You could convert the time to the "America/Los_Angeles" timezone before storing. Alternatively, you can convert it back after retrieving it, with something like this:

private DateFormat getDateFormat(String timezone) {
  DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  TimeZone tz = TimeZone.getTimeZone(timezone);
  return df;

private Date getDateWithCorrectedOffset(long timestamp, DateFormat source, DateFormat target) throws ParseException {
  Date d = new Date(timestamp);
  return target.parse(source.format(d));

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

Need Your Help

Debug in Eclipse : inspect variable -> errors durring evaluation

java eclipse debugging

I'm working on a piece of code Java and I have a dump problem.

URL Rewrite all broken

apache mod-rewrite url-rewriting rewrite

I am in a crisis at the moment, i overwrote my .htaccess file which had a lot of URL Rewrites that I did 6 months ago. Now I have to redo them all because I can't get half of my website to work wi...