2

I'm really hoping you can help me with this. I have a date outputted by a python program that I need to be able to access in another program.

The problem is that I have no idea how this date is formatted:

Format               Date
129893779638930000 - 2012-08-13 17:32:43

It is both date and time, and I'm really hoping somebody recognizes what format it is in, as I don't know python very well. Bonus points if you can show me how to convert it to a unix timestamp.

EDIT: The program that does this is a component for Foobar2000 (an extension for a music program). The component is shown here: http://www.foobar2000.org/components/view/foo_playcount, and it is the XML export feature that generates the odd date/timestamp.

6
  • Do you mean that 129893678626216000 should decode to 2012-08-13 14:44:22, and you’re trying to find the decoding algorithm? Commented Aug 14, 2012 at 7:08
  • Yes, exactly, which is why I know it isn't a variant of the unix timestamp. Commented Aug 14, 2012 at 7:10
  • Do you have the source code for the program that outputs it? If not, can you at least hint at what that program is? I don’t know but this could be a domain-specific convention or something. Commented Aug 14, 2012 at 7:14
  • Definitely, sorry I didn't think it would be helpful as it is a compiled dll, but again I don't know much about python, it might be decompilable. It's a component to Foobar2000 - foobar2000.org/components/view/foo_playcount. The XML export is what uses the odd encoding of date/timestamps Commented Aug 14, 2012 at 7:16
  • Another thing, it says somewhere it uses a 64 bit file time "A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC)", but I have no clue what that is (not a python guy) Commented Aug 14, 2012 at 7:20

4 Answers 4

12

129893678626216000 looks like the unix timestamp in 1e-8 seconds (tens of nanoseconds): 1,298,936,786.262,160,00. It would represent:

>>> from datetime import datetime
>>> datetime.utcfromtimestamp(129893678626216000/1e8)
datetime.datetime(2011, 2, 28, 23, 46, 26, 262160)

EDIT: However your information "A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC)" tells me to use:

>>> from datetime import datetime, timedelta
>>> datetime(1601, 1, 1, 0, 0, 0) + timedelta(seconds = 129893678626216000/1e7)
datetime.datetime(2012, 8, 13, 21, 44, 22, 621599)

where you get exactly what you awaited.

You can also convert it directly to unix timestamp (number of seconds since 1970-01-01 00:00:00 UTC):

>>> 129893678626216000 / 1e7 - 11644473600
1344894262.6215992
Sign up to request clarification or add additional context in comments.

3 Comments

By doing the division first, you risk running into floating point resolution limits. Better to do the subtraction first: (129893678626216000 - 116444736000000000) / 10000000.
P.S. converting to the Unix timestamp mathematically rather than bouncing through datetime is a good idea, since it eliminates time zone considerations.
P.S.S Or use timezone-aware epoch. Note that utcfromtimestamp is deprecated since 3.12. See its docs for safer alternatives.
3

It seems like Windows file time:

A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). The system records file times when applications create, access, and write to files. The NTFS file system stores time values in UTC format, so they are not affected by changes in time zone or daylight saving time. The FAT file system stores time values based on the local time of the computer. For example, a file that is saved at 3:00pm PST in Washington is seen as 6:00pm EST in New York on an NTFS volume, but it is seen as 3:00pm EST in New York on a FAT volume.

See also FILETIME Structure.

The important bit is that the time might be both in UTC and local timezone. If there might be FAT filesystem; check whether the plugin reads the filetimes directly from disk without any transformations to find out whether you need take into account local timezone.

For UTC case (adapting C++ answer):

WINDOWS_TICK_INTERVAL  = 100e-9 # 100 nanoseconds intervals
SEC_TO_UNIX_EPOCH = (datetime(1970, 1, 1) - datetime(1601, 1, 1)).total_seconds()
# -> 11644473600

def WindowsTickToUnixSeconds(windowsTicks):
    return windowsTicks * WINDOWS_TICK_INTERVAL - SEC_TO_UNIX_EPOCH

To convert it to datetime object:

from datetime import datetime

filetime = 129893779638930000
dt = datetime.utcfromtimestamp(WindowsTickToUnixSeconds(filetime))
print(dt.strftime("%Y-%m-%d %H:%M:%S.%f-00:00"))
# -> 2012-08-14 00:32:43.893000-00:00

It seems correspond to the time in your question: 2012-08-13 17:32:43-07:00 (maybe PDT).

To handle DST for filetimes in local timezone (from FAT) from the past you might need pytz library.

Comments

1

All is happy with the world, a filetime is like a unix timestamp but measured from 12:00 A.M. January 1, 1601, so subtracting the right amount of seconds and dividing to seconds gives you a unix timestamp, try this: (FILETIME - 116444736000000000) / 10000000

Comments

1

Given that the original data was a Windows FILETIME:

Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).

And the OP's data of:

Format               Date
129893779638930000 - 2012-08-13 17:32:43

As of Python 3.12 the recommendation is to use time zone-aware datetime to compute UTC offsets. Display in whatever time zone you like. The OP's data appears to be displayed as Pacific Time Zone (UTC-8 standard time or UTC-7 daylight savings time):

# May need "pip install -U tzdata" for latest time zone data on some OSes.
import datetime as dt
import zoneinfo as zi  # uses system's time zone data if available, or "tzdata" as fallback.

EPOCH = dt.datetime(1601, 1, 1, tzinfo=dt.timezone.utc)
result = EPOCH + dt.timedelta(seconds=129893779638930000 / 1e7)
print(result.astimezone(tz=zi.ZoneInfo('PST8PDT')))

# Since it is time zone-aware, this is the correct Unix timestamp:
print(result.timestamp())  # seconds since 1970-01-01 00:00:00 UTC

Output (agrees with OP's number/datetime)

2012-08-13 17:32:43.893000-07:00
1344904363.893

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.