Merge pull request #928 from wking/iso-8601

utils: Add some ISO 8601 forms to get_date()
This commit is contained in:
Justin Mayer 2013-06-14 08:27:37 -07:00
commit 6fcb6d3766
3 changed files with 75 additions and 33 deletions

View file

@ -286,7 +286,10 @@ by the directory in which the file resides. For example, a file located at
``python/foobar/myfoobar.rst`` will have a category of ``foobar``. If you would
like to organize your files in other ways where the name of the subfolder would
not be a good category name, you can set the setting ``USE_FOLDER_AS_CATEGORY``
to ``False``.
to ``False``. When parsing dates given in the page metadata, Pelican supports
the W3C's `suggested subset ISO 8601`__.
__ `W3C ISO 8601`_
If you do not explicitly specify summary metadata for a given post, the
``SUMMARY_MAX_LENGTH`` setting can be used to specify how many words from the
@ -478,3 +481,4 @@ metadata. That article will then be output to the ``drafts`` folder and not
listed on the index page nor on any category page.
.. _virtualenv: http://www.virtualenv.org/
.. _W3C ISO 8601: http://www.w3.org/TR/NOTE-datetime

View file

@ -6,9 +6,11 @@ import os
import datetime
import time
import locale
from sys import platform
from sys import platform, version_info
from tempfile import mkdtemp
import pytz
from pelican.generators import TemplatePagesGenerator
from pelican.writers import Writer
from pelican.settings import read_settings
@ -37,26 +39,44 @@ class TestUtils(LoggedTestCase):
def test_get_date(self):
# valid ones
date = datetime.datetime(year=2012, month=11, day=22)
date_hour = datetime.datetime(year=2012, month=11, day=22, hour=22,
minute=11)
date_hour_sec = datetime.datetime(year=2012, month=11, day=22, hour=22,
minute=11, second=10)
dates = {'2012-11-22': date,
'2012/11/22': date,
'2012-11-22 22:11': date_hour,
'2012/11/22 22:11': date_hour,
'22-11-2012': date,
'22/11/2012': date,
'22.11.2012': date,
'2012-22-11': date,
'22.11.2012 22:11': date_hour,
'2012-11-22 22:11:10': date_hour_sec}
date_hour = datetime.datetime(
year=2012, month=11, day=22, hour=22, minute=11)
date_hour_sec = datetime.datetime(
year=2012, month=11, day=22, hour=22, minute=11, second=10)
date_hour_sec_z = datetime.datetime(
year=2012, month=11, day=22, hour=22, minute=11, second=10,
tzinfo=pytz.timezone('UTC'))
date_hour_sec_est = datetime.datetime(
year=2012, month=11, day=22, hour=22, minute=11, second=10,
tzinfo=pytz.timezone('EST'))
date_hour_sec_frac_z = datetime.datetime(
year=2012, month=11, day=22, hour=22, minute=11, second=10,
microsecond=123000, tzinfo=pytz.timezone('UTC'))
dates = {
'2012-11-22': date,
'2012/11/22': date,
'2012-11-22 22:11': date_hour,
'2012/11/22 22:11': date_hour,
'22-11-2012': date,
'22/11/2012': date,
'22.11.2012': date,
'22.11.2012 22:11': date_hour,
'2012-11-22 22:11:10': date_hour_sec,
'2012-11-22T22:11:10Z': date_hour_sec_z,
'2012-11-22T22:11:10-0500': date_hour_sec_est,
'2012-11-22T22:11:10.123Z': date_hour_sec_frac_z,
}
# invalid ones
invalid_dates = ['2010-110-12', 'yay']
if version_info < (3, 2):
dates.pop('2012-11-22T22:11:10-0500')
invalid_dates.append('2012-11-22T22:11:10-0500')
for value, expected in dates.items():
self.assertEqual(utils.get_date(value), expected, value)
# invalid ones
invalid_dates = ('2010-110-12', 'yay')
for item in invalid_dates:
self.assertRaises(ValueError, utils.get_date, item)

View file

@ -180,17 +180,39 @@ def get_date(string):
If no format matches the given date, raise a ValueError.
"""
string = re.sub(' +', ' ', string)
formats = ['%Y-%m-%d %H:%M', '%Y/%m/%d %H:%M',
'%Y-%m-%d', '%Y/%m/%d',
'%d-%m-%Y', '%Y-%d-%m', # Weird ones
'%d/%m/%Y', '%d.%m.%Y',
'%d.%m.%Y %H:%M', '%Y-%m-%d %H:%M:%S']
formats = [
# ISO 8601
'%Y',
'%Y-%m',
'%Y-%m-%d',
'%Y-%m-%dT%H:%M%z',
'%Y-%m-%dT%H:%MZ',
'%Y-%m-%dT%H:%M',
'%Y-%m-%dT%H:%M:%S%z',
'%Y-%m-%dT%H:%M:%SZ',
'%Y-%m-%dT%H:%M:%S',
'%Y-%m-%dT%H:%M:%S.%f%z',
'%Y-%m-%dT%H:%M:%S.%fZ',
'%Y-%m-%dT%H:%M:%S.%f',
# end ISO 8601 forms
'%Y-%m-%d %H:%M',
'%Y-%m-%d %H:%M:%S',
'%Y/%m/%d %H:%M',
'%Y/%m/%d',
'%d-%m-%Y',
'%d.%m.%Y %H:%M',
'%d.%m.%Y',
'%d/%m/%Y',
]
for date_format in formats:
try:
return datetime.strptime(string, date_format)
date = datetime.strptime(string, date_format)
except ValueError:
pass
raise ValueError("'%s' is not a valid date" % string)
continue
if date_format.endswith('Z'):
date = date.replace(tzinfo=pytz.timezone('UTC'))
return date
raise ValueError('{0!r} is not a valid date'.format(string))
class pelican_open(object):
@ -510,15 +532,11 @@ def file_watcher(path):
def set_date_tzinfo(d, tz_name=None):
""" Date without tzinfo shoudbe utc.
This function set the right tz to date that aren't utc and don't have
tzinfo.
"""
if tz_name is not None:
"""Set the timezone for dates that don't have tzinfo"""
if tz_name and not d.tzinfo:
tz = pytz.timezone(tz_name)
return tz.localize(d)
else:
return d
return d
def mkdir_p(path):