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
astimezone
constructor
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