{"id":709,"date":"2012-08-05T12:46:41","date_gmt":"2012-08-05T12:46:41","guid":{"rendered":"http:\/\/www.sitekickr.com\/blog\/?p=709"},"modified":"2012-08-05T12:46:41","modified_gmt":"2012-08-05T12:46:41","slug":"sqlite-javascript-date","status":"publish","type":"post","link":"https:\/\/www.sitekickr.com\/blog\/sqlite-javascript-date\/","title":{"rendered":"SQLite dates and JavaScript formatting"},"content":{"rendered":"<p>If I were to guess, I&#39;d say that at least 50% of all database tables I create for any system contain a timestamp field. I think anyone could agree that this is a pretty commonplace. Given the importance and frequency of date operations, I&#39;m a little surprised that JavaScript doesn&#39;t natively handle them a little better.<\/p>\n<p>Don&#39;t get me wrong, JavaScript is one of my favorite languages, and I don&#39;t mean to put it down. But, if you&#39;ve logged any time developing in a language like ColdFusion, you&#39;re used to ridiculously simple date operations. In ColdFusion, I could use the following and expect a decent result:<\/p>\n<p>&lt;cfoutput&gt;#DateFormat(now(), &quot;give me a nice looking date&quot;)#&lt;\/cfoutput&gt;<\/p>\n<p>Okay, a slight exaggeration, but it gets the point across. Not to say date\/time formatting is impossible in JavaScript, far from it. Thanks to the pervasiveness of JavaScript, we are able to find a function for just about anything on the web.<\/p>\n<p>The inspiration for this post came from my dealings with the SQLite database, which as anyone would expect, doesn&#39;t measure up to the major players like MySQL and Oracle. But how could it, it runs in a browser. And with browsers sending out new releases every 5 minutes (FireFox, yes, I&#39;m talking about you), we can also expect changes to the SQLite engine as a much faster rate than we&#39;re used to. In my case, it was the use of timestamp fields which I struggled with. <\/p>\n<p>Many posts throughout the web suggested the use of a syntax similar to:<\/p>\n<p><code>CREATE TABLE IF NOT EXISTS mytable (<br \/>\n\t&nbsp;&nbsp; my_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,<br \/>\n\t&nbsp;&nbsp; my_field1 VARCHAR NOT NULL<br \/>\n\t&nbsp;&nbsp; my_created DATETIME DEFAULT (datetime(&#39;now&#39;, &#39;localtime&#39;)));<br \/>\n\t<\/code><\/p>\n<p>While syntactically correct, and did not throw any run-time errors, the above code didn&#39;t actually store a date\/time value, but rather just <em>null<\/em>.<\/p>\n<p>Some further searching brings me to newer posts about the subject, which indicate that in newer versions of SQLite, the preferred syntax is:<\/p>\n<p><code>CREATE TABLE IF NOT EXISTS mytable (<br \/>\n\t&nbsp;&nbsp; my_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,<br \/>\n\t&nbsp;&nbsp; my_field1 VARCHAR NOT NULL<br \/>\n\t&nbsp;&nbsp; my_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP);<\/code><\/p>\n<p>This worked beautifully, and stored the dates in the ODBC date format that I&#39;ve grown to love over the years (YYYY-MM-DD HH:MM:SS). But, wouldn&#39;t it figure that this format can&#39;t be parsed by JavaScript!<\/p>\n<p>After a brief period of annoyance, I did some more searching, and found the following function which will convert a date from this UTC format (yes, I&#39;m so old school that I call it ODBC format) to one that can be parse by JavaScript.<\/p>\n<p><code>function dateFromUTC( dateAsString, ymdDelimiter ) {<br \/>\n\t&nbsp;&nbsp;&nbsp; var pattern = new RegExp( &quot;(\\\\d{4})&quot; + ymdDelimiter + &quot;(\\\\d{2})&quot; + ymdDelimiter + &quot;(\\\\d{2}) (\\\\d{2}):(\\\\d{2}):(\\\\d{2})&quot; );<br \/>\n\t&nbsp;&nbsp;&nbsp; var parts = dateAsString.match( pattern );<\/p>\n<p>\t&nbsp;&nbsp;&nbsp; return new Date( Date.UTC(<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp; parseInt( parts[1] )<br \/>\n\t&nbsp;&nbsp;&nbsp; , parseInt( parts[2], 10 ) - 1<br \/>\n\t&nbsp;&nbsp;&nbsp; , parseInt( parts[3], 10 )<br \/>\n\t&nbsp;&nbsp;&nbsp; , parseInt( parts[4], 10 )<br \/>\n\t&nbsp;&nbsp;&nbsp; , parseInt( parts[5], 10 )<br \/>\n\t&nbsp;&nbsp;&nbsp; , parseInt( parts[6], 10 )<br \/>\n\t&nbsp;&nbsp;&nbsp; , 0<br \/>\n\t&nbsp;&nbsp;&nbsp; ));<br \/>\n\t}<br \/>\n\t<\/code><\/p>\n<p>I apologize to the fella who wrote this code, I can&#39;t seem to locate your post. The best I can do is not claim this as my own!<\/p>\n<p>As a bonus, here&#39;s another piece of code which I, again, pulled from the web, but modified for our SQLite timestamp related needs. It will display a human readable date as a function of the current date\/time (i.e. 5 minutes ago).<\/p>\n<p><code>function prettyDate(time){<br \/>\n\t&nbsp;&nbsp;&nbsp; if(!time)<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return &#39;&#39;;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; var date = new Date( dateFromUTC(time, &#39;-&#39;) ),<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff = (((new Date()).getTime() - date.getTime()) \/ 1000),<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; day_diff = Math.floor(diff \/ 86400);<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; if ( isNaN(day_diff) || day_diff &lt; 0)<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return &#39;&#39;;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; return day_diff == 0 &amp;&amp; (<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff &lt; 60 &amp;&amp; &quot;just now&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff &lt; 120 &amp;&amp; &quot;1 minute ago&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff &lt; 3600 &amp;&amp; Math.floor( diff \/ 60 ) + &quot; minutes ago&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff &lt; 7200 &amp;&amp; &quot;1 hour ago&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; diff &lt; 86400 &amp;&amp; Math.floor( diff \/ 3600 ) + &quot; hours ago&quot;) ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; day_diff == 1 &amp;&amp; &quot;yesterday&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; day_diff &lt; 7 &amp;&amp; day_diff + &quot; days ago&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; day_diff &lt; 60 &amp;&amp; Math.ceil( day_diff \/ 7 ) + &quot; weeks ago&quot; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (day_diff &gt;= 60 &amp;&amp; day_diff &lt; 600) &amp;&amp; Math.ceil(day_diff \/ 30) + &#39; months ago&#39; ||<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; day_diff &gt;= 600 &amp;&amp; Math.ceil(day_diff \/ 365) + &#39; years ago&#39;;<br \/>\n\t}<br \/>\n\t<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>If I were to guess, I&#39;d say that at least 50% of all database tables I create for any system contain a timestamp field. I&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"amp_status":""},"categories":[5,132,190,13],"tags":[180,194],"_links":{"self":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/709"}],"collection":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/comments?post=709"}],"version-history":[{"count":1,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/709\/revisions"}],"predecessor-version":[{"id":710,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/709\/revisions\/710"}],"wp:attachment":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media?parent=709"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/categories?post=709"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/tags?post=709"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}