--- author: '' category: '' date: 2013/05/29 10:06:47 description: '' link: '' priority: '' slug: javascript-makes-me-cry-turning-a-date-into-a-string tags: programming, rant title: 'Javascript Makes Me Cry: Turning a Date into a String' type: text updated: 2013/05/29 10:06:47 url_type: '' --- .. sidebar:: Disclaimer This is a rant because I spent 15 minutes doing things that feel wrong. If you are a JS programmer, and I wrote anything untrue or wrong, please comment, and I will fix it .. sidebar:: **Updates and Corrections** There is an interesting `discussion about this post at reddit `_, including a regexp-based solution (?!) Apparently, Java uses 0-based months, and so does C in the tm struct from time.h (except of course C also provides strftime, so none of this would have happened) C stores the year in a tm struct as a 1900-offset in an int. Since ints are guaranteed to be at least 16-bit, it's crap how C does it, too. It does have the excuse of having defined that in the 70s, when people naively thought noone would use that language in the year 2000 and everyone actually stored dates as two-digit numbers, paying for the college fund of all COBOL programmers' children in years to come. I refuse to accept as reasonable that the Javascript creators looked at the C stdlib and decided it was a good idea to expose "months are 0-based" and "years are 1900-offset" and not strftime and sprintf. **A better solution** `thejsjunky `_ had a great idea: solve this server side and just put the value in the template. **GetYear is worse than you think** because in IE8 and earlier it returns the same as ``getFullYear`` so it just can't be used reliably. Working late last night in `Alva `_ I wanted to do something that sounded trivial: When the page loads, get the current date and time, and if a certain input is empty, put it there like this: 28/05/2013 23:45 So, how hard can that be, right? Well not hard, but... Getting the current date-time is easy: ``now = new Date();`` So, is there something like `strftime `_ in Javascript? **Of course not**. You can get code from the usual places and have a untested, perhaps broken, limited version of it. And I am not about to add a strftime implementation to use it **once**. Sure, there are a number of Date methods that convert to strings, but **none of them lets you specify the output format**. So, let's try to do this The Javascript Way, right? To get the elements I want to put in the value, I used accessor methods. So, obviously, these should give me what I want for the string, right? ``now.getDay(), now.getMonth(), now.getYear(), now.getHour() now.getMinute()`` Well, they are, at the date mentioned above, respectively: 2, 4, 113, error, error Ok, the errors are easy to fix from the docs. It's actually ``getHours()`` and ``getMinutes()``, so now we have 2, 4, 113, 23, 45 and of those five things, the last two are what one would expect, at least. Let's go over the other three and see why they are so weird: ``Date.getDay()`` returned 2 instead of 28 Because ``getDay()`` gives you the **week day** and not the day of the month. Which is absolutely idiotic. So, you have to use ``getDate()`` instead. Which means the name is a lie, becasue the logical thing for ``getDate()`` to return is **the whole date**. ``Date.getMonth()`` returned 4 instead of 5 Because ``getMonth()`` returns months in the [0,11] range. Which is beyond idiotic and bordering in evil. Come on, Javascript, people have been referring to may as "5" for nearly two thousand years now! What other language does this? Anyone knows one? ``Date.getYear()`` returned 113 instead of 2013 Because it uses offset-from-1900. Which is amazing, and I had never *heard* of a language doing in a standard type. Because why? So, use ``getFullYear()`` instead. Now, armed with the right 5 numbers, let's format it. Does Javascript have the equivalent of `sprintf `_ or `format `_ ? **Of course not**. In JavaScript, without 3rd party modules, you create strings by addition, like a caveman. Again, I know I **could** add a format method to the String prototype and make this work, but I am not adding an implementation of format or sprintf just to use it once! So, this produces that I want:: now.getDate()+'/'+(now.getMonth()+1)+'/'+now.getFullYear()+' '+now.getHours()+':'+now.getMinutes() **Unless...** the day or month are lower than 10, in which case it's missing the left-padding zero. Luckily, for the purpose I was using it, it worked anyway. Because **OF COURSE** there's no included function to left-pad a string. You have to do it by addition. Or, of course, add a 3rd party function that's out there, in the internet, somewhere.