Ian Whiffin
Posted: 27th Jan 2020
Revised: 23rd February 2020 Tweet #share
One of the earliest tools that I made to make my forensicating easier was a timestamp converter. Despite there being a good number of great tools out there, I decided that writing my own tool would be a good way to learn more about the various timestamps that different systems use ranging from familiar timestamps such as UNIX and MAC Absolute to the somewhat more obscure like GPS Time.
As I coded it, I started to add more and more features that eventually made it my timestamp tool of choice. Features such as Auto-Detecting a timestamp type, respecting timezone offsets, reversing timestamps and calculating time differences (including a feature that allowed timestamp corrections to be made on incorrect clocks such as you may find on a DVR).
I've been trying to get around to rewriting this tool for a while now to refine it from it's initial state. It is now what I believe to be one of the most useful standalone time conversion tools available. It's not got the entire range of features that the earlier version had yet but those features will be added soon.
For now, I thought it would be nice to take a closer look at the different timestamps that Epoch works with. If you can think of an additional timestamps that I've missed, please contact me and I'll try to get it updated.
I have noticed that some timestamps are called different things by different people and for different purposes. I've tried to be generic in my naming but you may know some of these as something else.
Example : The current time in UNIX TimeStamp is 00000000.
Epoch Date
1st January 1970
Unit
Seconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of seconds since midnight on 1st January 1970.
Put even more simply, a UNIX TimeStamp of 1 would be 00:00:01 on 1st January 1970. A UNIX TimeStamp of 60 would be 00:01:00 on 1st January 1970. And so on.
Convert your own UNIX TimeStamp here :
=
UNIX MilliSecond
Example : The current time in UNIX MilliSecond TimeStamp is 00000000.
Epoch Date
1st January 1970
Unit
MilliSeconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of milliseconds (thousandth of a second) since midnight on 1st January 1970.
Put even more simply, a UNIX Millisecond TimeStamp of 1 would be 00:00:00 on 1st January 1970. A UNIX Millisecond TimeStamp of 1000 would be 00:00:01 on 1st January 1970. And so on.
Convert your own UNIX MilliSecond TimeStamp here :
=
UNIX 32bit (Hex)
The UNIX 32bit Hex Timestamp can be shown in either Big or Little Endian.
Example : The current time in UNIX 32bit Hex (Big Endian) TimeStamp is 00000000.
Example : The current time in UNIX 32bit Hex (Little Endian) TimeStamp is 00000000.
Epoch Date
1st January 1970
Unit
Seconds
Expression
Hex
TimeZone
UTC
This timestamp is simply the UNIX time (seconds since midnight on 1st January 1970) expressed as Hex.
Convert your own UNIX MilliSecond (Big Endian) TimeStamp here :
=
Convert your own UNIX MilliSecond (Little Endian) TimeStamp here :
=
Apple MAC Absolute
Example : The current time in MAC Absolute TimeStamp is 00000000.
Example : The current time in MAC Absolute (NanoSeconds) TimeStamp is 00000000.
Epoch Date
1st January 2001
Unit
Seconds or NanoSeconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of seconds since midnight on 1st January 2001.
Put even more simply, a MAC Absolute TimeStamp of 1 would be 00:00:01 on 1st January 2001. A MAC Absolute TimeStamp of 60 would be 00:01:00 on 1st January 2001.
This timestamp may also be expressed as a long number which is the number of nanoseconds since midnight on 1st January 2001.
Put even more simply, a MAC Absolute TimeStamp of 1 would be 00:00:01 on 1st January 2001. A MAC Absolute TimeStamp of 60 would be 00:01:00 on 1st January 2001.
Convert your own MAC Absolute TimeStamp here :
=
Convert your own MAC Absolute (NanoSecond) TimeStamp here :
=
Apple MAC HFS+
Example : The current time in MAC HFS+ TimeStamp is 00000000.
Epoch Date
1st January 1904
Unit
Seconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of seconds since midnight on 1st January 1904.
Put even more simply, a MAC HFS+ TimeStamp of 1 would be 00:00:01 on 1st January 1904. A MAC HFS+ TimeStamp of 60 would be 00:01:00 on 1st January 1904
Convert your own MAC HFS+ TimeStamp here :
=
Apple MAC HFS+ (Hex)
Example : The current time in MAC HFS+ (Hex - Big Endian) TimeStamp is 00000000.
Example : The current time in MAC HFS+ (Hex - Little Endian) TimeStamp is 00000000.
Epoch Date
1st January 1904
Unit
Seconds
Expression
Hex
TimeZone
UTC
This timestamp is expressed as a hex which is the number of seconds since midnight on 1st January 1904.
Put even more simply, a MAC HFS+ TimeStamp of 1 would be 00:00:01 on 1st January 1904. A MAC HFS+ TimeStamp of 60 would be 00:01:00 on 1st January 1904
Convert your own MAC HFS+ (Big Endian) TimeStamp here :
=
Convert your own MAC HFS+ (Little Endian) TimeStamp here :
=
Apple WebKit
Example : The current time in Apple Webkit TimeStamp is 00000000.
Epoch Date
1st January 2001
Unit
Seconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a decimal number which is the number of seconds since midnight on 1st January 2001. However, this timestamp is shown with a decimal number that appears to do nothing.
I'm sure there is a valid reason for it and it may well be an important level of accuracy or uniqueness in some circumstances. But for real-world purposes, simply ignoring everything after the decimal seems perfectly fine.
Convert your own MAC Apple Webkit TimeStamp here :
=
Apple Plist
Example : The current time in Apple Plist TimeStamp is 00000000.
Epoch Date
1st January 2001
Unit
Seconds
Expression
Decimal
TimeZone
UTC
This timestamp is basically the same as the Apple WebKit time but is expressed as Hex. It is the number of seconds since midnight on 1st January 2001.
Convert your own MAC Apple Plist TimeStamp here :
=
DOS FileTime
The DOS TimeStamp can be viewed in either Date/Time or Time/Date order. The method for calculating both is the same however.
Example : The current time in DOS (Date/Time)TimeStamp is 00000000.
Example : The current time in DOS (Time/Date) TimeStamp is 00000000.
Epoch Date
N/A
Unit
N/A
Expression
Hex
TimeZone
Local
Start by splitting the byte up into two nibbles. These represent the Date and Time (Or Time and Date).
In this example I will use the Date/Time format.
3050C57B
Date
Time
3050
C57B
Next, the nibbles need to be switched around to read in the opposite endian.
3050C57B
Date
Time
3050
C57B
5030
7BC5
Now convert the values into Binary
CA7B3050
50307BCA
Date
Time
5030
7BC5
0101000000110000
0111101111000101
The Binary is then broken up into sections.
Note that only 5 bits are available to record the seconds. That would usually mean a maximum number of seconds of 31 (16 + 8 + 4 + 2 + 1). We obviously need more than that but there aren't enough bits available. The decision was made that accuracy to 2 seconds would be enough. That meant that you can assume that the least significant bit is always 0. So by adding a 0 to the right side, you end up with 6 bits.
Bit 1
Bit 2
Bit 3
Bit 4
Bit 5
Bit 6
Max Value
1
1
1
1
1
31
1
1
1
1
1
0
62
Inserting the bit in red at the end shifts all bits to the left
CA7B3050
50307BCA
Date
Time
5030
7BC5
0101000000110000
0111101111000101
Bits
Value
Description
Bits
Value
Description
0-6
0101000
Year
0-4
01111
Hour
7-10
0001
Month
5-10
011110
Minute
11-15
10000
Day
11-15
001010
Second
Each Binary value is converted back into Decimal:
CA7B3050
50307BCA
Date
Time
5030
7BCA
0101000000110000
0111101111001010
Bits
Value
Description
Bits
Value
Description
0-6
0101000
40
Year
0-4
01111
15
Hour
7-10
0001
1
Month
5-10
011110
30
Minute
11-15
10000
16
Day
11-15
001010
10
Second
So you have the 16th January 40AD at 15:30:10... Oh wait... You may have realised that the year is a little off.
When this timestamp was created, they realized that seconds, minutes, hours, days and months are all finite, with top values of 60, 60, 24, 31 and 12 respectively. Years however presents an issue as they go on (hopefully) almost infinitely.
To combat this, the developers decided that 1980 would be a good place to start and so the YEAR value is added to 1980 in every case. In the example above, the year value is 40. Therefore, 1980 + 40 = 2020.
So the final date is 16th January 2020 at 15:30:10.
Note that these are always LOCAL TIME.
Convert your own DOS Date/Time TimeStamp here :
=
Convert your own DOS Time/Date TimeStamp here :
=
BlackBerry 7 Email
The BlackBerry 7 Email Timestamp is remarkably similar to the DOS FileTime with the exception of the year.
Example : The current time in BlackBerry 7 Email TimeStamp is 00000000.
Epoch Date
N/A
Unit
N/A
Expression
Hex
TimeZone
Local
Split the Byte up into two nibbles. These represent the Date and Time.
303748BD
Date
Time
3037
48BD
Now convert the values into Binary
303748BD
Date
Time
3037
48BD
0011000000110111
0100100010111101
The Binary is then broken up into sections.
303748BD
Date
Time
3037
48BD
0011000000110111
0100100010111101
Bits
Value
Description
Bits
Value
Description
0-6
0011000
Year
0-4
01001
Hour
7-10
0001
Month
5-10
000101
Minute
11-15
10111
Day
11-15
11101
Second
Each Binary value is converted back into Decimal:
Note that only 5 bits are available to record the seconds. That would usually mean a maximum number of seconds of 31 (16 + 8 + 4 + 2 + 1). We obviously need more than that but there aren't enough bits available. The decision was made that accuracy to 2 seconds would be enough. That meant that you can assume that the least significant bit is always 0. So by adding a 0 to the right side, you end up with 6 bits.
Bit 1
Bit 2
Bit 3
Bit 4
Bit 5
Bit 6
Max Value
1
1
1
1
1
31
1
1
1
1
1
0
62
Inserting the bit in red at the end shifts all bits to the left
303748BD
Date
Time
3037
48BD
0011000000110111
0100100010111101
Bits
Value
Description
Bits
Value
Description
0-6
0011000
24
Year
0-4
01001
9
Hour
7-10
0001
1
Month
5-10
000101
5
Minute
11-15
10111
23
Day
11-15
111010
58
Second
The developers of this timestamp decided that 1996 would be a good place to start and so the YEAR value is added to 1996 in every case. In the example above, the year value is 24. Therefore, 1996 + 24 = 2020.
So the final date is 23rd January 2020 at 09:05:58.
Note that these are always LOCAL TIME.
Convert your own BlackBerry Email TimeStamp here :
=
Windows 128bit
Example : The current time in Windows 128bit Hex (Big Endian) is 00000000.
Epoch Date
N/A
Unit
N/A
Expression
Hex
TimeZone
UTC
This timestamp is expressed as a 128bit hex number which breaks down into several parts.
Take the example time D9070B00010002000600090013000000.
First, it requires splitting into chunks of 2 bytes which must then be converted into decimal.
D9070B00010002000600090013000000
Split
D907
0B00
0100
0200
0600
0900
1300
0000
Swapped
07D9
000B
0010
0002
0006
0009
0013
0000
Converted
2009
11
16
2
6
9
13
0
The Converted values are then;
D9070B00010002000600090013000000
Split
D907
0B00
0100
0200
0600
0900
1300
0000
Swapped
07D9
000B
0001
0002
0006
0009
0013
0000
Converted
2009
11
1
2
6
9
13
0
Assignment
Year
Month
Day Of Week
Day
Hr
Min
Sec
MSec
Convert your own Windows 128bit TimeStamp here :
=
Windows 64bit (Hex)
Windows 64bit Hex can be displayed in Big or Little Endian.
Example : The current time in Windows 64bit Hex (Big Endian) is 00000000.
Example : The current time in Windows 64bit Hex (Little Endian) is 00000000.
Epoch Date
1st January 1601
Unit
Ticks
Expression
Hex
TimeZone
UTC
This timestamp is expressed as a hex number which is the number of ticks (one ten-millionth of a second) since midnight on 1st January 1601.
Convert your own Windows 64bit Hex (Big Endian) TimeStamp here :
=
Convert your own Windows 64bit Hex (Little Endian) TimeStamp here :
=
Google Chrome
Example : The current time in Google Chrome TimeStamp is 00000000.
Epoch Date
1st January 1601
Unit
MicroSeconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of microseconds (one millionth of a second) since midnight on 1st January 1601.
Put even more simply, a Google Chrome TimeStamp of 1000000 would be 00:00:01 on 1st January 1601. A Google Chrome TimeStamp of 60000000 would be 00:01:00 on 1st January 1601
Convert your own Google Chrome TimeStamp here :
=
FireFox
Example : The current time in FireFox TimeStamp is 00000000.
Epoch Date
1st January 1970
Unit
MicroSeconds
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of microseconds (one millionth of a second) since midnight on 1st January 1970.
Convert your own FireFox TimeStamp here :
=
Windows Ticks
Example : The current time in Windows Ticks is 00000000.
Epoch Date
1st January 0001
Unit
Ticks
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of ticks (one ten-millionth of a second) since midnight on 1st January 0001.
Put even more simply, a Windows Tick of 10000000 would be 00:00:01 on 1st January 0001. A windows Tick of 600000000 would be 00:01:00 on 1st January 0001. And so on.
Convert your own UNIX TimeStamp here :
=
Windows Cookie
Example : The current time in Windows Cookie Time is 00000000.
Epoch Date
1st January 1601
Unit
Ticks
Expression
Decimal
TimeZone
UTC
This timestamp is displayed in two parts, separated by a comma.
Example : 481435648,30788937
Separate the two parts of the value and convert to hex.
481435648,30788937
481435648
30788937
1CB22000
1D5CD49
Now Swap the values around and combine them into one value before converting back to a decimal.
481435648,30788937
481435648
30788937
1CB22000
1D5CD49
1D5CD49
1CB22000
1D5CD491CB22000
132237477975040000
The resulting number is the number of Ticks (one ten-millionth of a second) since since midnight on the 1st January 1601.
1st January 1601 + 132237477975040000 Ticks = 2020/01/17 15:16:37
Convert your own Windows Cookie Time here :
=
Microsoft OLE Automation (32bit)
Example : The current time in Microsoft OLE is 00000000.
Epoch Date
30th December 1899
Unit
Days / Fraction of day
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of days (including fractions) since midnight on 30th December 1899.
Convert your own OLE (32bit)TimeStamp here :
=
Microsoft OLE Automation (64 bit)
Example : The current time in Microsoft OLE (64bit) is 00000000.
Epoch Date
30th December 1899
Unit
Days / Fractions of days
Expression
Decimal
TimeZone
UTC
This timestamp is expressed as a long number which is the number of days (including fractions) since midnight on 30th December 1899.
It is represented using the IEEE754 Floating Point Standard.
Original Hex
BBD13DBF8B69E540
Swapped Endian
40E5698BBF3DD1BB
Float
43852.367094907408
Once you have the float, the decimal point is used to split the value. To the left of the decimal is the number of days since 30th December 1899. To the right of the decimal is the fraction of a day.
So 0 would be midnight, .25 would be 6AM, .5 would be 12PM and .75 would be 6PM.
Original Hex
BBD13DBF8B69E540
Swapped Endian
40E5698BBF3DD1BB
Float
43852.367094907408
Split Float
43852
367094907408
30th December 1899 + 43852 Days
36.7% of the day (1 day = 86400 seconds).
Wed 22 Jan 2020
31700 seconds
Wed 22 Jan 2020 08:48:36 (UTC 00:00)
Convert your own OLE(64bit) TimeStamp here :
=
Hotmail Time
Example : The current time in Hotmail Time is 00000000.
Epoch Date
1st January 1601
Unit
Ticks
Expression
Decimal
TimeZone
UTC
This timestamp is expressed in Hex as the number of ticks (one ten-millionth of a second) since midnight on 1st January 1601.
Split the value into two parts
6DCED501:803179C1
6DCED501
803179C1
Each part needs to switch endianess;
6DCED501:803179C1
6DCED501
803179C1
01D5CE6D
C1793180
Join the two parts as one large hex value and convert it to decimal.
6DCED501:803179C1
6DCED501
803179C1
01D5CE6D
C1793180
01D5CE6DC1793180
132238734870000000
The resulting value is the number of ticks.
So 1st January 1601 + 132238734870000000 Ticks = 19 JAN 2020 02:11:27
Convert your own Hotmail TimeStamp here :
=
Semi-Octet
Example : The current time in Semi-Octet TimeStamp is 00000000.
Epoch Date
N/A
Unit
N/A
Expression
Hex
TimeZone
Local
This timestamp is displayed using 6 bytes; One for Year, Month, Day, Hour, Minute., Second..
Byte 1
Byte 2
Byte 3
Byte 4
Byte 5
Byte 6
Byte 7
Year
Month
Day
Hour
Minute
Second
TimeZone
To complicate matters a little, the nibbles aren't in the right order however. So where a nibble may show the value 91, you have to swap the nibbles around to get the value 19.
So the value 91 01 52 10 91 52 would be 19 10 25 01 19 25... Or 2019/10/25 01:19:52.
The Timezone offset is in 15 minute increments. So if byte 7 was 04 then the offset value would be 15mins * 4 = 1hour from UTC.
Note that the year is only shown as 2 digits. Based on the usage of this timestamp being primarily for things that occurred in the past or present (ie. sent messages) then I have made the presumption that the dates cannot be in the future and assigned the century appropriately.
Simply, if the 2 digit year on the timestamp if equal or less than the current year, then the current century is presumed. If the year in the timestamp is higher than the current year, then last century is presumed. This may not work in all cases so is something to be aware of when using this timestamp.
Convert your own Semi-Octet TimeStamp here :
=
GPS Time
Example : The current time in GPS TimeStamp is 00000000.
Epoch Date
6th January 1980
Unit
Seconds
Expression
Decimal
TimeZone
UTC
GPS Time is a the number of seconds since 6th Jan 1980.
What makes GPS Time unique is the inclusion of Leap Seconds; seconds that are occasionally added to compensate for the earth's uneven rotation.
Since 1980, only 18 Leap Seconds have ever been added. They have always been added one at a time at either the end of June or end of December.
It is important to note;
Leap Seconds can be added or removed dependent on if the earth's rotation called for it
Multiple seconds could be added/removed at a time if required.
Leap Seconds could be applied at any time of year, however historically they have always been added at the end of June or end of December.
The decision to implement a Leap Second is made by The International Earth Rotation and Reference Systems Service (IERS).
Leap Seconds are unrelated to Leap Years with the exception that both are methods to correct an imperfect time system.
Example : The current time in Kai OS TimeStamp is 00000000.
Epoch Date
1st January 1970
Unit
MilliSeconds
Expression
Hex
TimeZone
UTC
This timestamp is ultimately the number of milliseconds (one millionth of a second) since midnight on 1st January 1970.
However, the number is then represented by the IEEE 754 Floating Point standard.
However, a much easer way to calculate this timestamp is to use a tool such as Hxd to view the original bytes as a Little Endian Double (Float64) to get the decimal value.
Example : The current time in Nokia Time is 00000000.
Epoch Date
1st January 2050
Unit
Seconds
Expression
Hex (Little Endian)
TimeZone
UTC
This timestamp is unique as it is the only one on this list that has an epoch which is in the future. This results (for now anyway) in a negative number being expressed.
The expressed number is simply 4 bytes of Hex which requires coverting to a decimal and subtracting from the future based epoch. (Technically, you need to add the negative number so that this method still works post 2050).
Convert your own Nokia TimeStamp here :
=
Wrapping Up
Thank you for reading! I envisage this post being much more of a reference tool than an interesting read but hopefully you've found a few things that you find useful. I plan on adding to this list as time (pardon the pun) goes on.
If you find any errors/omissions in this article, please let me know. I wrote this article relatively quickly and wrote encoding/decoding tools in both C# and Javascript simultaneously. Every effort has been made to ensure the results are correct but mistakes do happen.
Remember, you can download my free time tool Epoch from the software section of my site.