Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Javascript Makes Me Cry: Turning a Date into a String

Wo­rking la­te last ni­ght in Al­va I wanted to do so­me­thing that soun­ded tri­via­l:

When the pa­ge load­s, get the cu­rrent da­te and ti­me, and if a cer­tain in­put is emp­ty, put it the­re like this:

28/05/2013 23:45

So, how hard can that be, ri­gh­t? We­ll not har­d, bu­t...

Getting the current date-time is easy: now = new Da­te(); 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 ele­men­ts I want to put in the va­lue, I us­ed ac­ce­s­sor me­tho­d­s. So, ob­vious­l­y, the­se should gi­ve me what I want for the strin­g, ri­gh­t?

no­w.­ge­tDa­y(), no­w.­ge­t­Mon­th(), no­w.­ge­tYea­r(), no­w.­ge­tHou­r() no­w.­ge­t­Mi­nu­te()

We­ll, they are, at the da­te men­tio­ned abo­ve, res­pec­ti­ve­l­y: 2, 4, 113, erro­r, 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.

No­w, ar­med wi­th the ri­ght 5 num­ber­s, le­t's for­mat it. Does Ja­vas­cript ha­ve the equi­va­lent of sprin­tf or for­mat ? Of cour­se not. In Ja­vaS­crip­t, wi­thout 3rd par­ty mo­du­le­s, you crea­te strings by addi­tio­n, like a ca­ve­man. Agai­n, I know I could add a for­mat me­thod to the String pro­to­ty­pe and make this wo­rk, but I am not adding an im­ple­men­ta­tion of for­mat or sprin­tf just to use it on­ce!

So, this pro­du­ces that I wan­t:

now.getDate()+'/'+(now.getMonth()+1)+'/'+now.getFullYear()+' '+now.getHours()+':'+now.getMinutes()

Un­le­ss... the day or mon­th are lo­wer than 10, in whi­ch ca­se it's mis­sing the le­ft-­pa­dding ze­ro. Lu­cki­l­y, for the pur­po­se I was using it, it wo­rked an­ywa­y. Be­cau­se OF COUR­SE the­re's no in­clu­ded func­tion to le­ft-­pad a strin­g. You ha­ve to do it by addi­tio­n. Or, of cour­se, add a 3rd par­ty func­tion tha­t's out the­re, in the in­ter­ne­t, so­mewhe­re.

Striker / 2013-05-29 14:09:

I kindly direct you to http://momentjs.com/

Roberto Alsina / 2013-05-29 14:12:

Yes, I saw it mentioned, but I am not adding this: https://raw.github.com/timr... to avoid one ugly line :-)

alecu / 2013-05-29 15:31:

Mi opinión es que tenés que asumir las stdlib de javascript que implementan los browsers como lo que son: incompatibles, rotas, inútiles.

Y luego elegir para tus proyectos un par de bibliotecas buenas, como la que te sugieren acá y usar eso. Lo mismo que con CSS.

Matias Graña / 2013-05-29 14:17:

No sé si era una pregunta retórica, pero sobre otro lenguaje que sea "zero-based" para los meses, Java, en el paquete java.util.Calendar tiene ese hermoso comportamiento.

Roberto Alsina / 2013-05-29 14:21:

Argh? ;-)

Camilo Díaz Repka / 2013-05-29 14:30:

Exactamente, era parte de la movida para que "JavaScript sea lo más parecido a Java", copiado del horrible diseño de Calendar circa 1996/1998. Y como muchas otras cosas en software, simplemente quedó así.

nemo / 2013-05-29 19:39:

Your update thoughtfully does mention the origins in:
http://en.cppreference.com/...

"What other language does this? Anyone knows one?"
http://docs.oracle.com/java...
http://docs.oracle.com/java...
Is also 0-based month, 1900 based year. Perl does this too. Actually, is fairly common.

0 based month is convenient for arrays referencing month. Which was often used for, oh, localising the month string which was often the only string people had in a date.
1900 makes less sense, but common in languages from back then. Bit silly to be sure, but fairly harmless if you're aware of it.

nemo / 2013-05-29 19:41:

I'd also like to note you shouldn't use getYear in JavaScript ever, since while most browsers follow the specification and do the -1900 thing, IE8 and older do not.

Roberto Alsina / 2013-05-29 19:47:

Oh, extra fun :-)

Roberto Alsina / 2013-05-29 19:48:

Thanks for the comment!

nemo / 2013-05-29 20:46:

y = (new Array(count + 1 - x.toString().length)).join('0') + x;
For padding. Various other solutions listed here:
http://stackoverflow.com/qu...

Really though, I probably would just have called toLocaleFormat or toLocaleDateString- has advantage of being, oh, localised :)
And. Yes, the default JS API lacks a lot. Fortunately there are a ton of libs out there, so this is usually not a big deal.

nemo / 2013-05-29 21:02:

Oh... And +1 for doing server side. No reason not to support non-JS if possible.
Ok. Done now.

Roberto Alsina / 2013-05-29 21:04:

Yeah, saw some of those, and I can't describe my happiness when it worked without the padding ;-)


Contents © 2000-2020 Roberto Alsina