February 17, 2009 at 11:50 AM by Dr. Drang
TextMate’s Blogging Bundle has a problem with local timestamps in WordPress. I suppose what I should do is dig into the Ruby code for the bundle and try to fix it, but in the meantime I’ve written a short command that makes the necessary time adjustment.
Here’s the problem: I live in the US/Central timezone and want my posts to be timestamped with my local time. I have WordPress set up to handle things that way.
The Blogging Bundle has a Date header that allows me to set the date and time of the post I’m writing. If I include a line like
Date: 2009-02-17 11:50:05
in the header of my post and use the bundle’s Post to Blog command, that timestamp will be assigned to the post and WordPress will interpret it as my local time. If I don’t include a Date line in the header, the post will be stamped with whatever local time it was when I gave the Post to Blog command. In either case, the time is handled correctly. So far, so good.
After posting the article, the bundle updates the header lines in my TextMate document with all the info it got back from WordPress. Part of that info is the timestamp, which will turn into
Date: 2009-02-17 11:50:05 -0600
which is the same as before, but with the timezone offset appended to it. Still looks good.
Now let’s say I find a typo in the post. I fix the typo and issue the Post to Blog command again. And now the trouble begins. The timestamp of the post will be reset to six hours earlier than it was before (5:50 am), and the header line will change to
Date: 2009-02-17 05:50:05 -0600
If I make another edit issue another Post to Blog command, the timestamp will shift another six hours to
Date: 2009-02-16 23:50:05 -0600
A few more edits and the timestamp will be days before I actually wrote the post. This is not just a cosmetic problem in the TextMate document; the timestamp down at the bottom of the post will change, too, as will the time associated with the post in the WordPress database.
In summary, the initial post via the Blogging Bundle will carry the correct timestamp, whether the time is given explicitly or implicitly. But each successive update to the post will cause the timestamp to be shifted by the timezone offset.
The solution is to edit the Date header before updating the post. If I artificially set the header time to six hours later than the post’s actual time, e.g.,
Date: 2009-02-17 17:50:05 -0600
then the timestamp will remain where it was.
This is not only weird, it’s tiresome. Scroll up to the top of the document, add six hours to the time, advance the day if I’m posting after 6:00 pm, then go back and do the editing that I really want to do. Oh, and when I’m in Daylight Savings Time, the offset is five hours, not six, so I have to adjust the Date header by different amounts at different times of the year.
As I said earlier, the right way to fix this is to edit the
blogging.rb code in the bundle, but short of that, I’ve come up with a simple command that adjusts the Date header according to the timezone offset. Here’s the Python code:
1: #!/usr/bin/python 2: 3: import sys 4: import datetime 5: 6: post = sys.stdin.read().split('\n') 7: for line in post: 8: if line[:6] == 'Date: ': 9: date = datetime.datetime.strptime(line[6:25], "%Y-%m-%d %H:%M:%S") 10: tzString = line[25:] 11: tzhours = float(line[26:29]) 12: tzminutes = float(line[29:]) 13: offset = datetime.timedelta(hours=(tzhours + tzminutes/60)) 14: dateString = (date - offset).strftime("%Y-%m-%d %H:%M:%S") 15: print "Date: " + dateString + tzString 16: else: 17: print line
And here’s the setup in the TextMate Bundle Editor:
I have it bound to Control-Option-Command-D, which is easy to remember and to type. The timezone offset isn’t hard-coded into the script, it’s collected from the Date header line, so it adjusts with Daylight Savings Time. Lines 11-14 are written in a pretty general way and should work even if you live in one of those places with a fractional hour UTC offset.
I still have to remember to run the command (only once), but at least I don’t have to do modulo 24 arithmetic.