A Brief History of Time Stamps

Introduction

There are various methods of recording dates and times on computers and computing devices and as a forensic investigator, it is useful to understand the main formats and also to have an understanding of why dates are stored in the way that they are. For those of us who like to delve a little deeper into file formats some familiarity with how these dates ‘look’ in a hex dump can help when reverse engineering a new file format. During this short discourse, I will be presenting screenshots taken using software developed by Sanderson Forensics – RevEnge. RevEnge supports the decoding and display of all of the date formats discussed.

Why the plethora of formats?

In order to understand why we have so many date formats, it is useful to understand what we are trying to achieve when encoding a date and what the tradeoff between different methods are. The encoding used by early date formats was driven by the need to conserve space on disk and as such most dates were encoded using 4 bytes or 32 bits of storage space. This has required certain compromises in the accuracy and or the range of dates that can be encoded, such as the granularity of early MS-DOS dates being restricted to an accuracy of 2 seconds. A further consideration when designing a date format is the use to which that particular format is to put. For instance if a date is to be used in calculations then it is easier to add (for example) 1 year to a date that has the years recorded in a set number of bits (such as the MS-DOS date) than it is to add a year to say a UNIX date where account would need to be taken of the number of seconds in a given year (see leap years and leap seconds). Some date formats lend themselves to addition and subtraction better than others, i.e. the OLE automation time stores the date as a floating point number with the number of days since 30/12/1899 being the whole number part and the fractional part being the number of seconds since midnight.

The different formats

64-bit FileTime This is the ‘standard’ windows API file time structure and is stored as a 64-bit integer value representing the number of 100 nanosecond intervals since 01/01/1601[i]. This format is most commonly seen in NTFS MFT entries (there can be up to 20 in one MFT). When looking at Raw hex dates in this format can be recognized by a 64 bit run of data ending (or starting in the case of BigEndian data) with the hex values 01CB, to 01C7. FileTime data types can be identified in RevEnge by right-clicking on the data interpreters window and selecting “FileTime 64 bit” then moving the cursor through the data until a valid date is displayed in the data interpreters window. As there are many possible valid dates some of which (say 10/03/2099 might not be reasonable) RevEnge can be configured to highlight a reasonable valid date (say anything between 1/1/1990 and today’s date) in red.
In the screenshot above the date is highlighted in green with the first byte highlighted in the red square. As I am sure all readers are aware Microsoft use the LittleEndian storage format for integers (most significant bit first) so the above number would be written in hex 01C7AAC24034F21C, it is the numbers at the right of the date as shown in the hex which “tick over” faster, i.e. the numbers on the right represent the nano-seconds and the numbers on the left the years – hence the use of 01C7 (C701 in the hex above) to visually identify this as a possible date. The pattern of four similar strings also makes me think date especially as I know I am looking at an MFT entry where I would expect to see one or more dates (there are 8 obviously visible above).

Filetime (or file time formatted)

Is a file time as above but represented by two 32 bit integers which when taken together are decoded as above. Typically these formatted FileTimes are seen in email headers and the two halves are separated by a colon or period, an example of such a time stamp taken from an email is: X-OriginalArrivalTime: FILETIME=[1F53E680:01C902B8] The visual identifier for this date is again 01CB-01C7 but in this case, the identifier is in the second half of the 32-bit integer pairs, although somewhat obviously if the date is within an email it would normally be prefixed by a textual description.

HTML filetime

This is similar to the formatted FileTime above but the two 32 bit values are swapped An example of an HTML file time is shown below

ANSI SQL time

Two 32 bit integers, the first stores the number of days since 17 November 1858[ii], the second integer stores the number of 100 microsecond intervals since midnight

Java Time

A 64-bit integer value that specifies the number of milliseconds since January 1, 1970

OLE automation date

An 8 byte double precision floating point value. The integral portion is the number of days since 30/12/1899[iii], the fractional part records the fraction of the day (i.e. 0.5 is 12 hours i.e. noon, 0.25 is 6 hours i.e. 6am etc.)

MSDOS

The 32 bit date and time format used in the MSDOS and Windows FAT directory entry. Each portion of the time stamp (year, month etc.) is encoded within specific bits of the 32bit time stamp. The epoch for a DOS date is 1980 so this must be added to the date from bits 25-31. This format has a granularity of 2 seconds and the data is stored as follows:

 

Year Month Day Hour Min Seconds/2
Bits 31-25 24-21 20-16 15-11 10-5 4-0

MSDOS word swapped

This is a date format sometimes seen in tape archives and is the same as the above format with the upper and lower 16-bit words swapped.

Unix time

Sometimes referred to as C date and time and referenced by the type time_t by programmers, it is stored as a 32-bit integer and records the number of seconds since 1/1/1970[iv].

Unix time 48 bit

The date and time are stored as a 6-byte integer recording the number of milliseconds since 1/1/1970. Seen on Android devices.

AOL time

As for Unix time but recording the number of seconds since 1/1/1980[v] The example below shows the same 4 bytes decoded as both a Unix time and an AOL time, as expected the two dates are exactly 10 years apart.

Seconds Since (RevEnge configurable)

A generic form of Unix time added to RevEnge whereby the user can specify the epoch essentially it is the same as Unix or AOL time but the user chooses which date the clock starts counting from. This could conceivably be useful when an investigator is presented with a string of bytes which he/she knows to be a date and has other information informing him of what date the bytes should represent (I determined the GPS time referred to be in just this manner).

Unix decimal 10 byte

The 10 digit decimal representation of the number stored as a 32 bit Unix time, i.e. the date is recorded as a human-readable string and is quite common in web-based applications. The example below is from FaceBook chat.

Unix decimal 13 byte

As above using 13 digits and using the additional three digits to record the time as millisecond increments from 1/1/1970 Unix times can often be recognized as 10 or 13 digits numbers start with 11 or 12. They are also often prefixed by a textual reference which gives a clue, i.e. in the case of FaceBook the rather obvious string “ClientTime”
Another utility that can be used to decode dates and times is Craig Wilsons excellent DCode program, shown below:

GPS time

As for Unix time but recording the number of seconds since 6/1/1980[vi]

Fortran time

Again as for Unix time but recording the number of minutes since 1/1/1970

HFS time

Used in the Macintosh operating systems and records the number of seconds since 1st January 1904[vii] GMT. In HFS this is local time, in HFS+ this is GMT.

GSM dates

Are stored as nibble swapped data using 7 bytes as follows

Year Month Day Hour Min Sec Tz
Example 70 30 01 A0 C2 30 04

Decodes as 10/03/2007 10:44:03
The time zone byte represents the number of 15-minute intervals between local time and GMT

Decimal (Nokia S40) format dates

As above but the year can be stored as either a 2 byte little-endian or big-endian integer, there is no time zone information.

Binary Coded Decimal dates

Are stored as Binary Coded Decimal data using 6 bytes as follows

Year Month Day Hour Min Sec
Example 07 03 01 10 44 03

Decodes as 01/03/2007 10:44:03
ISO 8601 dates

A textual date format recording the date as YYYY-MM-DD hh:mm:ss

BitDate (seen on LG and Samsung phones)

A rather arbitrary name applied by me before I was aware of the devices on which this date format could be seen.

The date is stored as a 32-bit integer and the different components of the date are specified by different bits within the integer, in a similar manner to a DOS FAT date and time, however, there are no seconds recorded by the format.

i.e. the lowest 12 bits specify the year, the next 4 bits the month, then 5 bits each for the day & hour and then the last 6 bits for the minute.

  Year Month Day Hour Min Seconds
Bits 32-20 19-16 15-11 10-6 5-0 Not recorded