A Brief History of Time Stamps
IntroductionThere 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 formats64-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.
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 filetimeThis 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
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.)
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:
MSDOS word swappedThis 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 timeSometimes 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 bitThe date and time are stored as a 6-byte integer recording the number of milliseconds since 1/1/1970. Seen on Android devices.
AOL timeAs 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 byteThe 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 byteAs 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”
As for Unix time but recording the number of seconds since 6/1/1980[vi]
Again as for Unix time but recording the number of minutes since 1/1/1970
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.
Are stored as nibble swapped data using 7 bytes as follows
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
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.