10

I'm pulling a cookie expiration date from Google Chrome. From what it looks like, Chrome is storing cookie expirations with a timestamp that uses 1601-01-01 00:00:00 UTC as the epoch. My current implementation is as follows:

stamp = int(result[3])
date = datetime.datetime.fromtimestamp(stamp / 10000000.0)
print date.year

However, this is producing the wrong date (off by about a year). What am I doing wrong here?

martineau
  • 119,623
  • 25
  • 170
  • 301
Joshua Gilman
  • 1,174
  • 4
  • 16
  • 32

2 Answers2

12

Another option, getting tzinfo from the standard library since Python 3.2 (for older Python versions you can get if from pytz):

>>> import pytz
>>> from datetime import datetime, timedelta, timezone
>>> epoch = datetime(1601, 1, 1, tzinfo=timezone.utc)
>>> cookie_microseconds_since_epoch = 13022344559000000
>>> cookie_datetime = epoch + timedelta(microseconds=cookie_microseconds_since_epoch)
>>> str(cookie_datetime)
'2013-08-29 13:55:59+00:00'

I assume that the difference to your expected value is the timezones offset.

Update:

As @J.F.Sebastian correctly points out, if you are using implicit UTC naive datetime objects, tzinfo is redundant and the above can be simplified to:

>>> from datetime import datetime, timedelta
>>> epoch = datetime(1601, 1, 1)
>>> cookie_microseconds_since_epoch = 13022344559000000
>>> cookie_datetime = epoch + timedelta(microseconds=cookie_microseconds_since_epoch)
>>> str(cookie_datetime)
'2013-08-30 13:55:59'
Pedro Romano
  • 10,973
  • 4
  • 46
  • 50
1

I'm not sure what data you're starting with but here is an example starting from an integer timestamp. Assumes the pytz module is present (which I recommend highly).

>>> import datetime, pytz
>>> x = datetime.datetime.fromtimestamp(0)
>>> x = x.replace(tzinfo=pytz.UTC)
>>> str(x)
'1970-01-01 00:00:00+00:00'
>>> d = datetime.timedelta(365 * (1970 - 1601))
>>> str(x - d)
'1601-03-31 00:00:00+00:00'
>>> d = datetime.timedelta(365 * (1970 - 1601) + 31 + 28 + 31 - 1)
>>> str(x - d)
'1601-01-01 00:00:00+00:00'
>>> str(d)
'134774 days, 0:00:00'

So there you have it. Conversion between a Jan 1 1601 epoch and a Jan 1 1970 epoch is 134774 days.

Why that number of days? Leap years! We added a certain number of days, not years. (In fact, adding years is not directly supported in timedelta objects.)

wberry
  • 18,519
  • 8
  • 53
  • 85
  • This works, but I think Pedro Romano's solution, just calculating with the 1600-01-01 epoch instead of statically figuring out the 134774-day offset and calculating with that, is better (unless it's somehow a performance problem for a script that needs to be run millions of times or something…). – abarnert Sep 25 '12 at 21:49
  • Should be about the same performance-wise. His way, you compute the 1601 date against the 1970 epoch then add your time offset. This way, you treat the time offset as against 1970 then subtract the difference between epochs. – wberry Sep 26 '12 at 02:24