RFC #822 and RFC #3339 dates in Python
October 9, 2019
When adding a JSON feed and an RSS feed to
tumblelog I needed a publication date and
time for each article published. As I don't have an actual publication
time I decided to use the end of day, as explained in A Matter of
Time.
Edit: this blog post has been updated with additional code to make the RFC #822 solution work for a non-USA locale.
The end of day
In order to obtain a datetime Python object for the local end of day
for a given date I came up with the following idea:
- parse the date with a time of 23:59:59 attached to it
- create a new object using this result but in the local time zone
using the
astimezoneconstructor
I accomplished this in Python as follows:
def get_end_of_day(date):
return datetime.strptime(
f'{date} 23:59:59', '%Y-%m-%d %H:%M:%S').astimezone()
Calling this function with the date of today returns:
>>> get_end_of_day('2019-10-09')
datetime.datetime(2019, 10, 9, 23, 59, 59, tzinfo=datetime.timezone(datetime.tim
edelta(seconds=7200), 'CEST'))
Note the additional time zone data (tzinfo); Central European Summer
Time, which is correct for my location.
RFC #822
For the RSS feed I needed the pubDate to be in RFC #822
format, which I obtained as follows:
ctime = end_of_day.ctime()
pub_date = (f'{ctime[0:3]}, {end_of_day.day:02d} {ctime[4:7]}'
+ end_of_day.strftime(' %Y %H:%M:%S %z'))
Note that the short month name and the short day name are obtained
from ctime instead of returned by strftime. The reason for this is
that ctime returns those names in the USA locale, a requirement for
RFC #822.
Moreover, it's tempting to use %Z instead of %z but note that, for
example, CEST is not valid according to the RSS feed
validator, which refers to section
5.1 of RFC
#822. Hence, why
digits must be used instead for a general solution.
An example of a pub_date value is:
Wed, 09 Oct 2019 23:59:59 +0200
RFC #3339
For the JSON feed I needed a date_published in RFC #3339 format,
which was even easier to obtain as the string version of a datetime
is correct except for a space instead of a T:
date_published = str(end_of_day).replace(' ', 'T')
An example of a date_published value is:
2019-10-09T23:59:59+02:00
See Also
- datetime — Basic date and time types
- RFC #822 — Standard for ARPA Internet Text Messages
- RFC #3339 — Date and Time on the Internet: Timestamps
- Hand coding an RSS 2.0 feed in Python
- RFC #822 and RFC #3339 dates in Perl