{"id":5965,"date":"2010-07-20T00:29:00","date_gmt":"2010-07-19T15:29:00","guid":{"rendered":"http:\/\/haakondahl.com\/blog\/2010\/07\/20\/sql-active-directory-and-lastlogontimestamp\/"},"modified":"2010-07-20T00:29:00","modified_gmt":"2010-07-19T15:29:00","slug":"sql-active-directory-and-lastlogontimestamp","status":"publish","type":"post","link":"https:\/\/balldiamondball.com\/blog\/sql-active-directory-and-lastlogontimestamp\/","title":{"rendered":"SQL, Active Directory, and lastLogonTimestamp"},"content":{"rendered":"<p>There&#8217;s a fair bit of advice out there about converting the miserable integer8 (ANSI) date format into something you can use, but for some reason, none of it quite works for me.<\/p>\n<p>I have been using MS SQL SERVER 2005, which may or may not be a specific part of the problem.<\/p>\n<p>ANSI dates begin 1\/1\/1601, while Microsoft dates have, until recently, begun 1\/1\/1900. \u00a0Also, I believe MS dates are\/were measured in millisecond, but I&#8217;m not sure. \u00a0I do know that the ANSI timestamp is represented in units of 100 nanoseconds since 1\/1\/1601, which is where we start.<\/p>\n<p>If you grab the lastLogonTimestamp from Active Directory (say, by doing a <span class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\">csvde -m -f output.csv<\/span> and the using the Jet.4.0 connector to represent the directory as a linked server&#8217;s database and the csv file as a table&#8230;), you are presented with a number like 1.28nnnnnnnnnnnnnnnE+17, which is awful.<\/p>\n<p>There&#8217;s a formula out there which tells you to divide the bignum by 60, then by 100000000, then by 1440, and that&#8217;s all good, but the magic number there is divide by 864,000,000,000. \u00a0This will convert 100-nanosecond slices into the number of days passed since 1\/1\/1601 (with the decimal portion as usual representing the fractional part of a day, so that dd.75 means 6 in the evening on day dd), and I encourage you to work through the math yourself to prove it.<\/p>\n<p>But at this point, it is just a big floating-point number, and will display as such. \u00a0The problem comes in when you feed that number into a function such as <span class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\">CONVERT()<\/span>, and try to get a datetime representation. \u00a0It says that somebody&#8217;s last logon was in about the year 2309, which is not likely to be true. \u00a0This is where all the available guidance abandoned me, which is why I suspect that perhaps SQL SERVER 2005 does it a little differently&#8211;if it has borrowed Excel date functions from the 32-bit library, or something; I have no idea.<\/p>\n<p>On a hunch I took the <span class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\">DATEDIFF()<\/span> between 1\/1\/1900 and 1\/1\/1601, which yields 109,207. \u00a0This is the number of days between those dates. \u00a0I then subtracted that amount from the big float which purports to be a last logon time, and Voila! \u00a0The result was yesterday&#8217;s logon (from a midnight data pull).<\/p>\n<p>So for some reason, even when I brought the lastLogonTimestamp over in the fashion recommended by all of the guidance I could find, I wound up with my dates being interpreted as belonging to the wrong epoch.<\/p>\n<div style=\"text-align: center;\"><span class=\"Apple-style-span\" style=\"background-color: white;\"><span class=\"Apple-style-span\" style=\"font-size: x-large;\">Subtracting 109,207 (days) from a 1\/1\/1900-based date converts it to a 1\/1\/1601-based date.<\/span><\/span><\/div>\n<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"https:\/\/balldiamondball.com\/blog\/wp-login.php\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"5965\" data-trigger-type=\"like\" data-restriction=\"user\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><div class=\"pld-dislike-wrap  pld-common-wrap\">\r\n    <a href=\"https:\/\/balldiamondball.com\/blog\/wp-login.php\" class=\"pld-dislike-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"5965\" data-trigger-type=\"dislike\" data-restriction=\"user\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-down\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-dislike-count-wrap pld-count-wrap\"><\/span>\r\n<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>There&#8217;s a fair bit of advice out there about converting the miserable integer8 (ANSI) date format into something you can use, but for some reason, none of it quite works for me.<\/p>\n<p>I have been using MS SQL SERVER 2005, which may or may not be a specific part of the problem.<\/p>\n<p>ANSI dates begin 1\/1\/1601, while Microsoft dates have, until recently, begun 1\/1\/1900. \u00a0Also, I believe MS dates are\/were measured in millisecond, but I&#8217;m not sure. \u00a0I do know that the ANSI timestamp is represented in units of 100 nanoseconds since 1\/1\/1601, which is where we start.<\/p>\n<p>If you grab the lastLogonTimestamp from Active Directory (say, by doing a csvde -m -f output.csv and the using the Jet.4.0 connector to represent the directory as a linked server&#8217;s &#8230; <a href=\"https:\/\/balldiamondball.com\/blog\/sql-active-directory-and-lastlogontimestamp\/\"> Continue reading <span class=\"meta-nav\">&rarr; <\/span><\/a><\/p>\n","protected":false},"author":34128,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-5965","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/posts\/5965","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/users\/34128"}],"replies":[{"embeddable":true,"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/comments?post=5965"}],"version-history":[{"count":0,"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/posts\/5965\/revisions"}],"wp:attachment":[{"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/media?parent=5965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/categories?post=5965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/balldiamondball.com\/blog\/wp-json\/wp\/v2\/tags?post=5965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}