Missing timezone in metadata date can lead to wrong date in url #1069

Closed
zwippie opened this Issue May 9, 2013 · 34 comments

Projects

None yet
@zwippie
zwippie commented May 9, 2013

Starting with a fresh new Jekyll site with no modifications, I noticed that the first auto-generated post got the wrong page date when served. It looks like a missing timezone in the posts metadata can lead to the generated url being one day off when the time is close enough to midnight.

Metadata of file /_posts/2013-05-09/welcome-to-jekyll.markdown:


---
layout: post
title:  "Welcome to Jekyll!"
date:   2013-05-09 22:39:53
categories: jekyll update

---

This leads to the post having url /jekyll/update/2013/05/10/welcome-to-jekyll.html, which can be explained by me being in a timezone with offset +0200.

The url I expected to see was /jekyll/update/2013/05/09/welcome-to-jekyll.html.

Changing or removing the time part of the metadata (or adding timezone info) fixes the problem as expected, but it left me puzzled for a moment.

@zachgersh
Contributor

by chance, what is your system timezone set to?

@parkr
Member
parkr commented May 10, 2013

He says it's "+0200" above, which is my timezone as well. Central European.

@zachgersh
Contributor

Didn't you add specification of timezone to support just this issue?

@parkr
Member
parkr commented May 10, 2013

Yes, but there's an edgecase: if you don't specify the timezone when making posts and pages, it assumes it's UTC, I guess.

@zwippie
zwippie commented May 10, 2013

I'm sorry, I should have added that bit of information: System timezone in /etc/timezone is Europe/Amsterdam. To my best knowledge, Ruby uses that info. Also, adding the timezone to the config file did not change the situation. So what parkr says seems to be the case: the time/date is converted to UTC where it probably should not.

@parkr
Member
parkr commented May 10, 2013

i will look into this more, probably something i'd want to make into the gh pages release //cc @benbalter

@zachgersh
Contributor

So @parkr and I took a look at this and there seems to be nothing wrong with how the time / date are parsed (it always ends up in your local timezone).

I am not sure how your url would have rolled over like that. We checked to make sure the time didn't default to UTC or have any wonkiness.

Doesn't seem to be anything wrong at present with it.

@zwippie
zwippie commented May 12, 2013

@zachgersh I agree with you that no strange things seem to happen in ie. post.rb when it comes to parsing and formatting dates. If no one else experiences this one-day-off error then I guess there is something wrong on my side.

For the sake of completeness:

Linux Debian 6 kernel 2.6.32-5-amd64
rvm 1.15.7
ruby 1.9.3p194
Jekyll 1.01

@zachgersh
Contributor

Well, I don't want to claim it is not there just because I didn't experience it ๐Ÿ˜„

The only thing I could possibly think of is daylight savings having something to do with it but that feels like a stretch.

Just out of curiosity can you double check in your IRB that your offset is what you expect it to be from Ruby?

@zachgersh
Contributor

I think we can close this for now @parkr.

@zwippie please reopen if you stumble across this and have new info.

@parkr parkr closed this May 13, 2013
@ArieShout

I've experienced this issue on my first taste of Jekyll today.
The default timezone of my Mac OS X system is set to CST (+0800).

โžœ  ~  date
Fri Aug  2 17:29:51 CST 2013

The generated example post (by jekyll new blog) have metadata as followed:

---
layout: post
title:  "Welcome to Jekyll!"
date:   2013-07-30 17:57:28
categories: jekyll update
---

And after running jekyll serve, the URL for the post is

http://localhost:4000/jekyll/update/2013/07/31/welcome-to-jekyll.html

If I edit the date of the post in metadata to 2013-07-30 17:57:28+0800, everything works fine.

It seems that Jekyll parses the date in metadata with default timezone set to UTC (if no timezone info is specified in the date string), but then generates the link according to the system default timezone.

It would be better either 1) to generate system timezone aware date string in metadata when running jekyll new blog or 2) to parse the date in metadata with default timezone set to system timezone.

Thanks~

@parkr
Member
parkr commented Aug 5, 2013

Adding the timezone is a great idea! We also want to create generators which create new posts - we'll add it there as well.

@parkr
Member
parkr commented Aug 6, 2013

Rel: #1148.

@makkes
makkes commented Sep 3, 2013

Having to add the timezone to the date metadata is pretty awful. Why do I have to specify it in _config.yml, then? Why not just assume every date without a specified timezone to have the one specified in _config.yml?

@parkr
Member
parkr commented Sep 4, 2013

We can't make that assumption :( What if we provided a generator like in #1148?

@robkorv
Contributor
robkorv commented Oct 7, 2013

Hmm, breaking my head over this ;)
What I would expect is that it doesn't convert the time at all. Only when I explicitly tell jekyll that it should.

When I use date : 2013-08-04 22:14:12 on my machine it shouldn't convert it to 2013-08-05 00:14:12, because I'm on UTC+2.

I'm reading above that this shouldn't happen, is there something I'm missing?

@fugalh
fugalh commented Dec 8, 2013

I found that a bunch of my dates were off after an import even though it had given timezones. Changing date: YYYY-MM-DD HH:MM:ss.sssssss -08:00 to date: 'YYYY-MM-DD HH:MM:ss.sssssss -08:00' (note the quotes) corrected it. So try quotes and see if that makes things less confusing. sed -i "s/^date: \(2.*\)$/date: '\1'/" _posts/*

Not sure if this is illegal yaml, a yaml parsing problem, or something after

@gregRV
gregRV commented Aug 18, 2014

Very helpful, thanks for posting @zwippie

@dnozay dnozay added a commit to dnozay/dnozay.github.io that referenced this issue Nov 5, 2014
@dnozay dnozay change dates / timezone info. 0bff753
@alanguir
alanguir commented Mar 6, 2015

I'm experiencing this as an issue too, and it definitely feels broken. I'd only expect the output of the date filter to match UTC if I were, in fact, on UTC +0000. I didn't notice this when working just with dates, but it was immediately apparent when trying to work with hours.

IRB tells me I have my time set correctly

2.2.0 :001 > Time.now
 => 2015-03-06 11:57:35 -0500 

_config.yml has the timezone set correctly:

timezone: America/Detroit
markdown: kramdown
encoding: utf-8
...

Post front matter has a dates array in local time

dates:
  - start: 2015-3-23 18:00:00
    end: 2015-3-23 21:00:00
  - start: 2015-3-25 18:00:00
    end: 2015-3-25 21:00:00

No funky tricks in the date rendering:

{% for date in event.dates %}
  <li>{{ date.start | date: '%b %d, %Y  %l:%M %P' }} - {{ date.end | date: ' %l:%M %P' }}</li>
{% endfor %}

And the rendered HTML shows times in UTC. ( that should be 6pm (18:00) - 9pm(21:00), rather than 2pm and 5pm respectively ).

Mar 23, 2015 2:00 pm - 5:00 pm
Mar 25, 2015 2:00 pm - 5:00 pm

Miraculously, jekyll does correctly calculate daylight savings time by only rending the UTC time as -0400 instead of the usual -0500 for my part of the world.

ps - jekyll 2.5.3

@alanguir
alanguir commented Mar 6, 2015

Update: setting my timezone to Africa/El_Aaiun in _config.yml in the meantime to avoid adding the offset to each date in each post. Apparently that will give me the same DST rules as US Eastern time, and output my times as expected.

@parkr
Member
parkr commented Mar 6, 2015

@alanguir This behaviour is per safe_yaml and Time.parse when you give us a string. We set the TZ variable before these methods are executed, but if you have no offset, Ruby has no way to know what that time should be so it just forgets about it and assigns it to UTC at all times (IIRC). Going back and adding offsets is highly recommended. It can be a pain, but it's important, otherwise you have over 24 times in one (one per timezone), so there's no way to know what exact moment in time you're looking for.

@alanguir
alanguir commented Mar 6, 2015

@parkr I understand how this could cause unexpected results if I'm writing my times assuming UTC +5, and jekyll has a build script that runs when I deploy on a heroku server living in UTC +8, but why ignore the explicit timezone setting in the config file? That seems like a perfectly good way to know what the time should be.

What is the timezone config option used for if not helping jekyll parse dates at build time?

@parkr
Member
parkr commented Mar 7, 2015

What is the timezone config option used for if not helping jekyll parse dates at build time?

All it does is set $TZ in your Ruby environment. If you have no timezone data, it doesn't add anything in (it doesn't default to your local timezone). It makes me sad. I wrote a blog post about this sort of thing (though not this exact thing). Timezones in Ruby aren't great.

Think of it like excluded bits of data without a default.

@willnorris
Contributor

yep, I ran into the crappy support for timezones in Ruby when I switched to Jekyll too. In my case, I very specifically want to preserve the timezone of when a post was written, and display that on my site (for example, compare by-lines here vs here). For me, that additional bit of data is meaningful.

I do this by ensuring that I always specify dates as strings in my frontmatter (otherwise the yaml module will "helpfully" parse them as Time objects), and then use a custom jekyll plugin to parse the post date as a DateTime, which preserve timezone information. Not sure if that is helpful to others in this thread, but just wanted to point out one way I've worked around ruby's TZ shortcomings.

@parkr
Member
parkr commented Mar 7, 2015

@willnorris Do you see a bugfix path for safe_yaml or Jekyll in this regard?

@willnorris
Contributor

@parkr I've never actually looked closely at what safe_yaml does before, but now this does make sense: date.rb. It parses dates as DateTime, but then converts them to Time and always returns the value in local time. In my opinion, this is totally the wrong thing to do since (if I'm correctly understanding how time is handled in ruby) you're throwing away any TZ data that was there. I imagine having safe_yaml return the DateTime object would be a pretty major breaking change for them and not realistic. The only thing Jekyll could do is basically what I'm doing... if a date is specified as a string, then you could additionally parse it as a DateTime and preserve the TZ info that way.

@parkr
Member
parkr commented Mar 7, 2015

It parses dates as DateTime, but then converts them to Time and always returns the value in local time. In my opinion, this is totally the wrong thing to do since (if I'm correctly understanding how time is handled in ruby) you're throwing away any TZ data that was there.

So they fixed this in Ruby 2.2.0, which broke Jekyll's expectations that it'd be in your local timezone (that's what my blog post is about).

I imagine having safe_yaml return the DateTime object would be a pretty major breaking change for them and not realistic.

@dtao, how would you feel about this?

if a date is specified as a string, then you could additionally parse it as a DateTime and preserve the TZ info that way.

Right now we use Time.parse โ€“ should we switch to using DateTime.parse?

@willnorris
Contributor

It parses dates as DateTime, but then converts them to Time and always returns the value in local time. In my opinion, this is totally the wrong thing to do since (if I'm correctly understanding how time is handled in ruby) you're throwing away any TZ data that was there.

So they fixed this in Ruby 2.2.0, which broke Jekyll's expectations that it'd be in your local timezone (that's what my blog post is about).

Oh, interesting.. so I somehow missed that. So now this means that ruby 2.2 is preserving the TZ information correctly, but now it's Jekyll that is throwing it away by always calling localtime ๐Ÿ˜ž I know that this is how Jekyll has always worked historically and perhaps has some assumptions built in for this, but it still makes me sad because we're throwing away the data. If a post date is specified without TZ information, then sure treat it as localtime. But if an author has taken the effort to specify the TZ in the post date, then it seems very unfortunate that we don't respect and preserve that.

if a date is specified as a string, then you could additionally parse it as a DateTime and preserve the TZ info that way.

Right now we use Time.parse โ€“ should we switch to using DateTime.parse?

Maybe? I'm not sure where else Time and DateTime differ and what problems this could potentially introduce. I seem to recall that some of our date-related liquid filters choked on a DateTime, but don't remember fully.

@pathawks
Member
pathawks commented Mar 7, 2015

But if an author has taken the effort to specify the TZ in the post date, then it seems very unfortunate that we don't respect and preserve that.

๐Ÿ‘ This has also often bothered me.

@alanguir

To solve my specific issue, I wrote a tiny Jekyll filter that will apply your local timezone offset to a custom front matter date. Be careful when using with something like a heroku deploy script - I haven't tested there, although tzinfo is explicitly setting the timezone based on Jekyll config:

https://gist.github.com/alanguir/72c6d22d95f3ed80a511

@sumdog
sumdog commented May 12, 2015

I just started using Jeykll and just noticed this. I have converted posts from a legacy/proprietary system where each post had a date and a time (but no timezone). Everything was a full day off (My localtime is set to Australia/Melbourne).

I feel like if I don't specify a timezone, than those are the dates/times I want to use when displaying to the user. They really shouldn't go through any conversion at all. (and even if I do specify a timezone...there should really only be a conversion if the _config.yml has a different timezone). We're talking about static content here; not content that changes depending on the connecting browser.

There should be an option to disable any timezone alteration entirely, although judging from the comments, I'm not sure if that's entirely possibly if this is depending on the underlying YAML engine.

@envygeeks
Member

This is more than likely a problem with the object we use rather than the way we use the object, DateTime sucks when an explicit timezone isn't supplied and if I remember we are using DateTime objects?

@jaypinho

Just ran into the same problem here as well.

Posted something at 1:22 AM New York time (UTC - 4 hours) and put in the data without time zone as '2015-05-22 01:22:00' (assuming it would show up correctly since I have 'timezone: America/New_York' in my _config.yml file), but the URL slug and the post date both show up as the day before. This doesn't seem like the type of behavior you'd expect by default.

@davep davep added a commit to davep/davep.github.com that referenced this issue Jun 18, 2015
@davep davep Add date to first post
Also noticed that Jekyll has some issues with timezones. cf
jekyll/jekyll#1069
f0ecf74
@chemoish

Trying to follow years of timezone posts,,, It would be nice to be able to specify a time and have the timezone modify that time appropriately on compilation.

2017-02-12 14:30:00 + America/Los_Angeles = 2017-02-12 14:30:00 -0800
2017-04-02 14:30:00 + America/Los_Angeles = 2017-04-02 14:30:00 -0700

/shrug

@ctubbsii ctubbsii referenced this issue in apache/incubator-fluo-website Oct 14, 2016
Merged

Major refactoring of release posts #27

@e28eta e28eta added a commit to e28eta/e28eta.github.io that referenced this issue Feb 3, 2017
@e28eta e28eta Remove timezone from welcome post
Setting the _config timezone didn't solve the issue. Maybe I should add
timezone to all dates in all posts, but I'm going to try this first.
I'm not concerned about capturing the local time (I think).

Possibly related: jekyll/jekyll#1069
670dc78
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment