Zach’s ugly mug (his face)

Zach Leatherman

Yet Another Pretty Date JavaScript

March 23, 2008

I can’t let this Pretty Date thing go. I decided to use a modification of John Resig’s Pretty Date JavaScript implementation written by Dean Landolt and shared in the comments on John’s page. The script was an obvious choice for the next iteration of Alarmd, which is nearing completion as I type.

The more I used Dean Landolt’s script, the more problems I began to see with his implementation. It was a good start, but definitely had bugs. His assumptions translating from integer second differences to human readable labels stretched too far at times (there is an error in logic to say anything between 24 hours and 48 hours from now can be labeled “Tomorrow”), and he was a bit loose with his difference categories (assumed average month length was 28 days, and always used Math.floor instead of rounding — 47 hours from now would be labeled “1 Day”). It was great code otherwise, and I definitely liked the way he used the while loop to run through the comparisons.

So, I’ve cleaned up his great start, and am releasing it to the world in the spirit of cooperation and open sauce. You just read that typo out loud didn’t you?

Download: Yet Another Pretty Date Implementation (2 KB)

Update: Dates for this script must have a specific ISO8601 format: YYYY-MM-DDTHH:MM:SSZ (in UTC) where T and Z are literals.

Update: This script has been moved to Github.

Zach’s ugly mug (his face)

Zach is a builder for the web with Netlify. He created the Eleventy static site generator and is still fixated on web fonts. His public speaking résumé includes talks in eight different countries at events like Beyond Tellerrand, Smashing Conference, CSSConf, and The White House. He is an emeritus of Filament Group, NEJS CONF, and still helps out with NebraskaJS. Read more about Zach »

Architecture Choices: Callbacks and Events in JavaScript
Minor Annoyances with Firefox Development
25 Replies
    1. Dean Landolt Disqus

      25 Mar 2008 at 01:39PM
      Thanks for the fixes. I actually can't take credit for introducing those bugs (just completely missing them) -- I got that piece of code from a comment on Resig's original post which was actually the imputus for me to do the rewrite in the first place...I like your code a lot better than mine -- cleaner and easier to understand.
      1. Zach Leatherman Disqus

        25 Mar 2008 at 09:17PM
        Thanks Dean. I wouldn't have even noticed the problems had I not been trying to use the script for a project.Open source moves solely due to impetus sometimes.
        1. Jauder Ho Disqus

          27 Mar 2008 at 06:33AM
          Cool. This came in useful. Thanks for hacking this out.
          1. Zach Leatherman Disqus

            28 Mar 2008 at 04:15AM
            I appreciate the comment. I hope someone else gets some good use out of it.
            1. Gary Sherman Disqus

              05 May 2008 at 08:39PM
              Zach,Very nice! This is exactly what I was looking for.Thanks for sharing!
              1. it is really nice script.
                1. unwiredbrain Disqus

                  28 Jun 2008 at 02:28PM
                  Very nice work.But there's something I really don't get: if I'm using a future date (think about a dtstart / dtend duet, like hCalendar does), the script treats them as past events!If current year is 2008 and I'm planning some event for year 2009, the script says "1 Year Ago"! This is undoubtedly wrong! And should be avoided, of course.For me, the problem resides in the first if clause: seconds should not be modified; if seconds are less than zero, then the script should do nothing, returning null.A null returning would be very comfortable, allowing control statements as John Resig did in his original scripts; in particular, would be comfortable because you would not soil the innerHTML.Also, if you avoid the token, all the script will instantly get more suitable for l10n, making the code more clean and readable.
                  1. unwiredbrain Disqus

                    29 Jun 2008 at 02:21AM
                    OK. Wait a sec. My previous comment clearly shows that I did not understand anything about your script. I apologize for that.But...I (think I) found a glitch -- from now on consider all the dates & everything treated as UTC: if you set a date to exactly now (where "now" is the instant where the page loads) the script returns a "2 Hours" -- I mean: future!Is to be said that I live in a country where right now the time zone is CEST that is GMT plus two hours (see Wikipedia for more), but, as you can easily imagine, in other countries this could vary: zero, one or two, like me, or even more.Now: all your script runs using UTC (which is good), but at line 34 you add the current local time zone offset, which is wrong in my opinion.I think that this should be fixed, but I look forward to your opinion.Anyway, I still think that you should never touch a future date, and I still think that by removing the token you'll get a more compact, readable and elegant code.PS: just FYI, here's my test case: the script vanilla, I get the glitch; removing the time zone offset I get the correct behavior.Also, you can test this by adding some minutes: just modify the 'difference' variable in the HTML document.I hope the whole thing is clearer now.Have a nice day.
                    1. Zach Leatherman Disqus

                      08 Jan 2009 at 12:57AM
                      @unwiredbrain I tried to check out your test script and it would seem that the link is down.Can you repost somewhere else, or include the code?I developed this for alarmd, so you can see it in action there. If you add an alarm, it will create a pretty date in the bottom right corner.For instance, I just added an alarm for +1h, resulting in 2009-01-08T02:56:38Z. I'm in CST (-6), which is is right (it's now 7:56PM).Thanks,Zach
                      1. unwiredbrain Disqus

                        08 Jan 2009 at 07:10AM
                        Zach,not receiving a reply for months I deleted all the relative documents; my documents deleted, down... Guess what? I had to recreate the glitch from scratch.Let's assume my current system date is 2008-01-08;Let's assume my current system time is 08:45:00;Let's assume my current time zone offset is +0100;Let's assume my current span looks like this:<span class="dtstart" title="2009-01-08T08:45:00Z+0100">Some event that just happened</span>On my test page, launching $(".dtstart").humane_dates() I will see "60 Minutes". Which is future.That's exactly my current local time added with my current local time zone offset.Apart from the glitch; being a future event, isn't it supposed to be left as it was -- i.e. not humanized at all?
                        1. I confirm what unwiredbrain says. The script adds the timezoneoffset to the current local time returning a humanized date that is in the '11 hours' no ago..
                          1. replacing line 34 with this fixes it for me:seconds = ((dt - new Date(time)) / 1000),
                            1. Zach Leatherman Disqus

                              21 Jan 2009 at 04:34AM
                              I BElIEvE THE scriPT SHOulD wOrK AS INtENDeD (aS is).It shoULD Be NOTed ThaT INcluding A tIMezonE offsET intO yoUr markUP daTE IS NOt a SUPPorTED uSE case fOR thiS SCRIpt. outPUTtIng Utc tImE OnlY (no HarDCoDeD ofFSets In thE datEs) aLlOWs FoR the JAVAScRiPT COde to iNtERpRET THe daTetO ThE OFfSET oF THe clieNt.I bELiEVe ThAT aDdING SuPpORt foR HArDcoDeD tIMeZONE OFfsets WOuLd AdD UNneCEsSAry ComplexITy To THE COdE. OutPuT z +/- 0 AnD IT wiLL WoRk fInE.tHat BEINg SaId, iF YoU diSAgrEe, FEEl FreE TO ModIfY thE scrIPt anD RE-RelEAsE IT! IT'S alL OPEN SOURCE.
                              1. whAtS aRE you tRying To DO wiTH tHE .REPLaCE(/[tz]/G, " ") caLl?IT enDs up reMOvIng AlL tHE LetTer TS. So SOmE dAtES fAIL.E.g. "thu fEB 5 08:02:38 psT 2009" Is PArsed as "hU FEB 5 08:02:38 pST 2009" and SuBSEquenTLY FAIls.
                                1. Zach Leatherman Disqus

                                  17 Mar 2009 at 12:10AM
                                  Hey Frank,Take a look at the Original Script, it's intended to take ISO8601 dates, such as "2008-01-28T20:24:17Z"The T and Z removal make more sense in that context.
                                2. Donny Kurnia Disqus

                                  18 Apr 2009 at 12:15PM
                                  Hi, I just find out this post from john post about pretty date.@unwiredbrainYou must change the date to shown in title attribute into GMT. So it must written as:Some event that just happenedSee that it is 7:45 in GMT, because your timezone is +01:00.The javascript will use the browser timezone setting, so the result will be correct.If you are using PHP in the server-side, this is the code to change timestamp into GMT (using server's timezone setting), then format it to become ISO.
                                  1. Donny Kurnia Disqus

                                    18 Apr 2009 at 12:20PM
                                    @webmackThe line 34 is to overcome the timezone setting in user's browser. Since the calculation is done in each user browser, the js script must know how much the time different is.If you remove the (dt.getTimezoneOffset() * 60000) addition, all user browser is assumed at GMT.The addition is proposed by Dean in the comment at john blog. So the date that must changed is the one in the html. It must in GMT.Check my previous comment to find the way to convert local server date into GMT, then show it as ISO format using PHP.
                                    1. Has anyone else noticed that this script, when implemented with JQuery, will not work on firefox 3? I'm trying to find a solution, but currently it just outputs the original date string, and does not format it...
                                      1. Zach Leatherman Disqus

                                        12 Jun 2009 at 01:03AM
                                        I use the script in ALARMd, so I know that it works in Firefox 3. What date are you trying to transform that doesn't work?
                                        1. Hi there, If you can help you will end hours of head scratching. The dates i'm working with look like: 2009-06-03 20:06:44+0000Firefox finds this as an invalid date.
                                          1. Zach Leatherman Disqus

                                            13 Jun 2009 at 01:38PM
                                            Hey Tristan, as mentioned in some of the previous comments, your dates should be ISO8601 using GMT:2009-06-03T20:06:44ZThanks!
                                            1. Sherman Monroe Disqus

                                              05 Aug 2011 at 03:00PM
                                              Small tweak, it wasn't accounting for GMT time, thus, it parsed 10:00 am CST, which is 15:00 GMT time, and told me "5 hours ago" when viewing it at 10:05 am. So I made the following change at line 34, but don't know how this will affect all cases:seconds = ((dt - new Date(time) + ((-dt.getTimezoneOffset()/60) * 60000)) / 1000),
                                              1. Zach Leatherman Disqus

                                                05 Aug 2011 at 05:35PM
                                                Hey Sherman,You can make your modification to the GitHub repo and run the unit tests: free to put in a Pull Request and I'll merge it in.Zach
                                                1. Johnie R Disqus

                                                  19 Oct 2011 at 01:07AM
                                                  Hey guys, I am pretty new to JS, but i am curious, if i wanted a date older than 4 weeks to say the actual date, how hard is that?Example: instead of saying 1 month ago, how about just September 18 @ 10:06PM.any feedback is appreciated. thanks.
                                                  1. Aravind NC Disqus

                                                    07 Feb 2012 at 09:43AM
                                                    You saved the day man !!! Thanks a lot
                                                      Social Card Image Preview

                                                      This is what will show up when you share this post on Social Media:

                                                      How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)