docpad icon indicating copy to clipboard operation
docpad copied to clipboard

date is off by one day when using custom metadata

Open motivic-dev opened this issue 13 years ago • 20 comments

I've been making posts with a custom metadata tag of 'created' to log the original date of the post. Like so:


---
layout: post
title: example
created: 2012-10-15

---

Then, in the post template (jade), I grab both the custom 'created' date, and the standard 'date' and turn them into date strings like so:

div#post-created !{ document.created.toDateString() }
div#post-edited !{ document.date.toDateString() }

Both date objects are found and parsed just fine, but the problem is that the custom date always displays as one day earlier than it should. So, in my example above where I set the 'created' date to 2012-10-15 the date gets output as 'Sun Oct 14 2012', when it should read 'Mon Oct 15 2012'.


Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.

motivic-dev avatar Oct 15 '12 22:10 motivic-dev

Hrmmm, perhaps node is running in a different timezone than yourself. Not sure how to change what timezone node uses, will need to look into it sometime.

balupton avatar Oct 16 '12 03:10 balupton

Not sure that's it, though. The time returned by the call to document.date is totally correct, only the custom document.created is off. Perhaps those are handled very differently, I've not looked into how that works.

I'll test out your idea, though. Perhaps if I make my 'created' metadata a more specific date object that includes a time, I can see if the time is off as well as the date. I have my doubts though, I've tried regenerating my site at many different times of day, and it's always off by exactly one calendar day. I'll let you know what comes of my test.

motivic-dev avatar Oct 16 '12 03:10 motivic-dev

Ok, so I'm pretty sure now that node is set to the correct time zone for me. I tried a test post with the following metadata:

---
layout: post
title: test
created: 2012-10-16T03:28:17.547Z
---

I then changed my template to say:

#post-creation-date !{ document.created.toString() }

and I got the following output upon generating:

'Mon Oct 15 2012 20:00:00 GMT-0400 (EDT)'

So, I asked for a generic date/time string, and it converted an ISOString to GMT-0400, which is my correct time zone, since I am in New York. It also completely ignored the time information I gave it though, so I'm not sure what to make of that. But at least I know that node knows I'm in GMT-0400.

motivic-dev avatar Oct 16 '12 03:10 motivic-dev

@motivic-dev would you be able to look into this further? Pretty short on time right now unfortunately.

balupton avatar Oct 22 '12 15:10 balupton

Also, what operating system, node version, docpad version are you using?

balupton avatar Oct 22 '12 15:10 balupton

Mac OSX 10.7.5 (Lion) Node v0.8.10 DocPad v6.7.4

Sure, I'll look into it further. I had given up and gone to just dating them one day later, makes me cringe every time, though :)

motivic-dev avatar Oct 22 '12 19:10 motivic-dev

I'm seeing this too using Eco instead of Jade.

Mac OSX 10.8.2 (Mountain Lion) Node v0.8.12 DocPad v6.7.4

scottoreilly avatar Oct 25 '12 04:10 scottoreilly

When I format the date like this: date: 2007-03-04

and then call @document.date.toString(), it returns

Sat Mar 03 2007 18:00:00 GMT-0600 (CST)

Note that the day of the month is off by 1. However, when I format the date like this: date: March 4, 2007

and then call @document.date.toString(), it correctly returns

Sun Mar 04 2007 00:00:00 GMT-0600 (CST)

scottoreilly avatar Oct 25 '12 04:10 scottoreilly

@scottoreilly thanks for that. For the getMonth thing, getMonth is spec'd to start at 0 and finish at 11 (reference) which would indicate that the getMonth output you're getting is correct. It still leaves the bug of days being one off though.

balupton avatar Oct 25 '12 05:10 balupton

Ah, ha! Ok, sorry about that. I've updated my comment to avoid confusion.

scottoreilly avatar Oct 25 '12 05:10 scottoreilly

I just hit this too.... really really really bizarre. Looking into it as it is preventing watching from working correctly.

balupton avatar Nov 23 '12 00:11 balupton

In my case, it turned out to be a separate issue that is fixed in the upcoming v6.12.0 - renames were not updating the mtime of the file/document

Will keep this open until the original issue is fixed...

balupton avatar Nov 23 '12 01:11 balupton

I ran into this issue too. I did a little research and it turns out to be a timezone issue coupled with how Date.parse picks local or GMT time based on whether the date conforms to an ISO-8601 format. See the following stackoverflow questions for a detailed explanation:

http://stackoverflow.com/questions/2587345/javascript-date-parse http://stackoverflow.com/questions/7556591/javascript-date-object-always-one-day-off

christurnertv avatar Apr 02 '13 03:04 christurnertv

Cool, glad we now know what the issue is. Anyone game enough to implement a solution into DocPad? Happy to accept a pull request for this.

Ideally, we should be able to just add UTC to the end of the date strings before parsing, however testing that locally doesn't seem to work as they remain the same timezone, however maybe someone else will get different resules:

$ node -e 'console.log(new Date("2011-09-24 UTC").toString())'
Sat Sep 24 2011 10:00:00 GMT+1000 (EST)

balupton avatar Apr 09 '13 02:04 balupton

Happy to have pull requests for this! Unfortunately I'm bogged down with client work, and my time zone doesn't suffer from this issue, so not sure when I'll get around to this unfortunately.

balupton avatar Apr 24 '13 11:04 balupton

@ervwalter is this what you were experiencing? https://botbot.me/freenode/docpad/msg/6770016/

balupton avatar Oct 10 '13 20:10 balupton

Yes, it is. As @gizmovation mentioned, the problem is that parsing a date like '2013-10-09' assumes midnight UTC on October 9th, instead of midnight local time. And so if you are west of the prime meridian, the date object will be one day earlier.

Are you ok "fixing" this even though it's possible that someone somewhere is depending on the current behavior? An easy fix, if you don't mind one more small dependency, is to use the moment.js node module to parse the date string as it has special handling for ISO-8601 style date strings to ensure that they are always consistently parsed.

If you're ok with a solution like that, I can prepare a pull request.

ervwalter avatar Oct 10 '13 20:10 ervwalter

Actually, I started working on a trial fix for this and it looks like the issue is deeper than I thought. I fixed the DocPad code to use moment() for parsing the date metadata property, but it is still broken. It turns out that the yamljs internally converts any property that looks like a YYYY-MM-DD formated date to a Date object with exactly the same problem. And DocPad never sees the string representation of the property, so by the time DocPad gets the metadata properties it's too late to do anything about it.

Short of opening an issue with yamljs and perhaps seeing if they are open to a flag that tells their code to not try to parse date strings, I don't know that there is much we can do in the DocPad codebase.

The easiest workarounds are to either always include a time, even if it is just 00:00, or to use a format that doesn't look like YYYY-MM-DD. For example, both 2013/10/11 and Oct 11, 2013 parse fine into local time.

ervwalter avatar Oct 12 '13 04:10 ervwalter

From memory the yamljs author is a DocPad user, so they should be quite receptive to getting this fixed :-) If you could file an issue on the yamljs issue and reference this issue in it, that would be great :-)

balupton avatar Oct 13 '13 08:10 balupton

Done :)

ervwalter avatar Oct 14 '13 15:10 ervwalter