{"id":42653,"date":"2003-09-05T07:00:02","date_gmt":"2003-09-05T14:00:02","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2003\/09\/05\/how-to-recognize-different-types-of-timestamps-from-quite-a-long-way-away\/"},"modified":"2021-02-03T20:42:13","modified_gmt":"2021-02-04T04:42:13","slug":"how-to-recognize-different-types-of-timestamps-from-quite-a-long-way-away","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20030905-02\/?p=42653","title":{"rendered":"How to recognize different types of timestamps from quite a long way away"},"content":{"rendered":"<p>The great thing about timestamps is that there are so many to choose from. Sometimes, while debugging (or reading incomplete documentation) you&#8217;ll find a timestamp and wonder how to convert it into something readable. Here are some tips.<\/p>\n<p>We will use November 26, 2002 at 7:25p PST as our sample time.<\/p>\n<p>UNIX timestamps are in seconds since January 1, 1970 UTC. It is a 32-bit number, the only 32-bit number in common use as a timestamp.<\/p>\n<p>November 26, 2002 at 7:25p PST = 0x3DE43B0C.<\/p>\n<p>If it&#8217;s a 32-bit value starting with &#8220;3&#8221;, it&#8217;s probably a UNIX time. (The &#8220;3&#8221; era began in 1995 and ends in 2004.)<\/p>\n<p>To convert these values to something readable, you have several choices.<\/p>\n<p>The C runtime time_t value is the same as a UNIX timestamp, so you can use the <code>ctime()<\/code> function, for example.<\/p>\n<p>This is the time format used by the C runtime and by the Windows NT event log.<\/p>\n<h2>Number two: The Win32 FILETIME<\/h2>\n<p>Win32 FILETIME values count 100-nanosecond intervals since January 1, 1600 UTC. It is a 64-bit number.<\/p>\n<p>November 26, 2002 at 7:25p PST = 0x01C295C4:91150E00.<\/p>\n<p>If it&#8217;s a 64-bit value starting with &#8220;01&#8221; and a letter, it&#8217;s probably a Win32 FILETIME. The &#8220;01A&#8221; era began in 1972 and the &#8220;01F&#8221; era ends in 2057.<\/p>\n<p>To convert these values to something readable, you can use the <code>FileTimeToSystemTime()<\/code> function followed by <code>GetDateFormat()<\/code> and <code>GetTimeFormat()<\/code>.<\/p>\n<h2>Number three: The CLR System.DateTime<\/h2>\n<p><strong>Warning: Actual .NET content<\/strong> (I&#8217;m sorry). CLR System.DateTime values count 100-nanosecond intervals since January 1, 1 UTC. It is a 64-bit number. These aren&#8217;t used much yet.<\/p>\n<p>November 26, 2002 at 7:25p PST = 0x08C462CB:FCED3800. (? somebody check my math)<\/p>\n<p>If it&#8217;s a 64-bit value starting with &#8220;08&#8221; and a letter, it&#8217;s probably a CLR System.DateTime. The &#8220;08A&#8221; began in 1970 and the &#8220;08F&#8221; era ends in 2056.<\/p>\n<p>To convert these values to something readable, construct a System.DateTime object passing the 64-bit time value as the constructor parameter.<\/p>\n<h2>Number four: The DOS date\/time format<\/h2>\n<p>The DOS date\/time format is a bitmask:<\/p>\n<pre>               24                16                 8                 0\r\n+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+\r\n|Y|Y|Y|Y|Y|Y|Y|M| |M|M|M|D|D|D|D|D| |h|h|h|h|h|m|m|m| |m|m|m|s|s|s|s|s|\r\n+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+\r\n \\___________\/\\________\/\\_________\/ \\________\/\\____________\/\\_________\/\r\n     year        month       day      hour       minute        second\r\n<\/pre>\n<p>The year is stored as an offset from 1980. Seconds are stored in two-second increments. (So if the &#8220;second&#8221; value is 15, it actually represents 30 seconds.)<\/p>\n<p>These values are recorded in <i>local time<\/i>.<\/p>\n<p>November 26, 2002 at 7:25p PST = 0x2D7A9B20.<\/p>\n<p>To convert these values to something readable, convert it to a FILETIME via DosDateTimeToFileTime, then convert the FILETIME to something readable.<\/p>\n<h2>Number five: OLE Automation date format<\/h2>\n<p>The OLE automation date format is a floating point value, counting days since midnight 30 December 1899. Hours and minutes are represented as fractional days.<\/p>\n<h2>Converting among these formats<\/h2>\n<p>Often there is no direct conversion between two formats; you will have to go through some intermediary formats.<\/p>\n<dl>\n<dt>UNIX timestamp to\/from Win32 FILETIME<\/dt>\n<dd>Converting a UNIX timestamp to a WIn32 FILETIME is described in <a href=\"http:\/\/support.microsoft.com\/kb\/167296\"> KB article Q167297<\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms724228\"> a scaled-down version of the article is also available in the Platform SDK<\/a>. Some high school algebra will get you the reverse conversion.<\/dd>\n<dt>FILETIME to\/from SYSTEMTIME<\/dt>\n<dd>Use FileTimeToSystemTime() and SystemTimeToFileTime().<\/dd>\n<dt>FILETIME to\/from System.DateTime<\/dt>\n<dd>Use System.DateTime.FromFileTime() and System.DateTime.ToFileTime().<\/dd>\n<dt>OLE date to\/from System.DateTime<\/dt>\n<dd>Use System.DateTime.FromOADate() and System.DateTime.ToOADate().<\/dd>\n<dt>DOS date\/time to\/from FILETIME<\/dt>\n<dd>Use DosDateTimeToFileTime() and FileTimeToDosDateTime().<\/dd>\n<dt>DOS date\/time to\/from SYSTEMTIME<\/dt>\n<dd>Parse it yourself.<\/dd>\n<dt>SYSTEMTIME to\/from OLE date.<\/dt>\n<dd>Use SystemTimeToVariantTime() and VariantTimeToSystemTime(), or use VarDateFromUdate() and VarUdateFromDate().<\/dd>\n<dt>DOS date\/time to\/from OLE date.<\/dt>\n<dd>Use DosDateTimeToVariantTime() and VariantTimeToDosDateTime().<\/dd>\n<\/dl>\n<p>Let&#8217;s see if I can draw a little chart.<\/p>\n<div id=\"p20030905_defs\">\u00a0<\/div>\n<p>I&#8217;m not sure that chart actually cleared up anything.<\/p>\n<p>If you allow yourself to use MFC, then there are some more conversions available.<\/p>\n<dl>\n<dt>UNIX time, FILETIME, SYSTEMTIME, or DOS date\/time to OLE date format.<\/dt>\n<dd>Use the MFC COleDateTime helper object.<\/dd>\n<\/dl>\n<p>I won&#8217;t bother trying to add these (unidirectional) arrows to the chart above.<\/p>\n<p><a href=\"https:\/\/blogs.msdn.microsoft.com\/brada\/\">Brad Abrams&#8217; blog<\/a> followed some of these arrows and produced <a href=\"https:\/\/blogs.msdn.microsoft.com\/brada\/2003\/07\/30\/converting-to-a-datetime-from-time_t\/\">a cute little formula to convert UNIX time_t directly to System.DateTime<\/a>.<\/p>\n<h2>Other time formats<\/h2>\n<p>JScript&#8217;s Date object constructor can construct from an integer representing milliseconds since 1970. This is the same as UNIX time, just multiplied by 1000.<\/p>\n<p><script>\n(function() {\n  var svg = {\n    defs: `<\/p>\n<div>&nbsp;<\/div>\n<p>` + \/* insert random junk to trick blog software into putting its garbage outside the svg element (also need to manually delete the p element that surrounds the script block *\/\n    `<svg stroke-width=\"1.7\" width=\"400\" height=\"150\">\n  <defs>\n    <marker id=\"arrowstart\" viewbox=\"0 0 8 8\" orient=\"auto\"\n            refX=\"2\" refY=\"4\" style=\"overflow:visible\">\n      <path d=\"M 8,8 L 0,4 L 8,0 C 7,2 7,6 8,8 Z\" \/>\n    <\/marker>\n    <marker id=\"arrowend\" viewbox=\"0 0 8 8\" orient=\"auto\"\n            refX=\"6\" refY=\"4\" style=\"overflow:visible\">\n      <path d=\"M 0,8 L 8,4 L 0,0 C 1,2 1,6 0,8 Z\" \/>\n    <\/marker>\n  <\/defs>\n  <text x=\"20pt\" y=\"10pt\">UNIX<\/text>\n  <line x1=\"40pt\" y1=\"15pt\" x2=\"40pt\" y2=\"25pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- UNIX <-> FILETIME -->\n  <text x=\"10pt\" y=\"40pt\">FILETIME<\/text>\n  <line x1=\"40pt\" y1=\"45pt\" x2=\"40pt\" y2=\"96pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- FILETIME <-> SYSTEMTIME -->\n  <line x1=\"70pt\" y1=\"36pt\" x2=\"95pt\" y2=\"36pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- FILETIME <-> DateTime -->\n  <text x=\"100pt\" y=\"40pt\">System.DateTime<\/text>\n  <line x1=\"140pt\" y1=\"45pt\" x2=\"140pt\" y2=\"96pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- DateTime <-> OLE -->\n  <text x=\"10pt\" y=\"110pt\">SYSTEMTIME<\/text>\n  <line x1=\"90pt\" y1=\"105pt\" x2=\"115pt\" y2=\"105pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- SYSTEMTIME <-> OLE -->\n  <text x=\"120pt\" y=\"110pt\">OLE date<\/text>\n  <text x=\"60pt\" y=\"70pt\">DOS date<\/text>\n  <line x1=\"60pt\" y1=\"45pt\" x2=\"70pt\" y2=\"56pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- FILETIME <-> DOS -->\n  <line x1=\"60pt\" y1=\"96pt\" x2=\"70pt\" y2=\"76pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- SYSTEMTIME <-> DOS -->\n  <line x1=\"120pt\" y1=\"96pt\" x2=\"100pt\" y2=\"76pt\" stroke=\"black\" marker-start=\"url(#arrowstart)\" marker-end=\"url(#arrowend)\" \/><!-- OLE <-> DOS -->\n<\/svg>`\n  };\n  Object.keys(svg).forEach(function (key) {\n    Array.prototype.forEach.call(document.querySelectorAll(\"#p20030905_\" + key),\n      function (e) {\n        e.innerHTML = svg[key];\n      });\n  });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The great thing about timestamps is that there are so many to choose from.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-42653","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The great thing about timestamps is that there are so many to choose from.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/42653","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=42653"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/42653\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=42653"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=42653"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=42653"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}