Django

Code

Ticket #1443: datetime_pre_1900.2.patch

File datetime_pre_1900.2.patch, 17.1 kB (added by SmileyChris, 2 years ago)

updated for recent change to date validator

  • django/core/validators.py

    old new  
    132132    # Could use time.strptime here and catch errors, but datetime.date below 
    133133    # produces much friendlier error messages. 
    134134    year, month, day = map(int, date_string.split('-')) 
    135     # This check is needed because strftime is used when saving the date 
    136     # value to the database, and strftime requires that the year be >=1900. 
    137     if year < 1900: 
    138         raise ValidationError, gettext('Year must be 1900 or later.') 
    139135    try: 
    140136        date(year, month, day) 
    141137    except ValueError, e: 
  • django/db/backends/util.py

    old new  
    11import datetime 
     2from django.utils import datetime_pg 
    23from time import time 
    34 
    45class CursorDebugWrapper(object): 
     
    4344############################################### 
    4445 
    4546def typecast_date(s): 
    46     return s and datetime.date(*map(int, s.split('-'))) or None # returns None if s is null 
     47    return s and datetime_pg.date(*map(int, s.split('-'))) or None # returns None if s is null 
    4748 
    4849def typecast_time(s): # does NOT store time zone information 
    4950    if not s: return None 
     
    7778        seconds, microseconds = seconds.split('.') 
    7879    else: 
    7980        microseconds = '0' 
    80     return datetime.datetime(int(dates[0]), int(dates[1]), int(dates[2]), 
     81    return datetime_pg.datetime(int(dates[0]), int(dates[1]), int(dates[2]), 
    8182        int(times[0]), int(times[1]), int(seconds), int(float('.'+microseconds) * 1000000)) 
    8283 
    8384def typecast_boolean(s): 
  • django/db/models/fields/__init__.py

    old new  
    88from django.utils.text import capfirst 
    99from django.utils.translation import gettext, gettext_lazy 
    1010import datetime, os, time 
     11from django.utils import datetime_pg 
    1112 
    1213class NOT_PROVIDED: 
    1314    pass 
     
    404405        Field.__init__(self, verbose_name, name, **kwargs) 
    405406 
    406407    def to_python(self, value): 
    407         if isinstance(value, datetime.datetime): 
    408             return value.date() 
    409         if isinstance(value, datetime.date): 
     408        if isinstance(value, datetime_pg.date): 
    410409            return value 
     410        if isinstance(value, (datetime.date, datetime.datetime)): 
     411            return datetime_pg.new_date_pg(value) 
    411412        validators.isValidANSIDate(value, None) 
    412413        try: 
    413             return datetime.date(*time.strptime(value, '%Y-%m-%d')[:3]) 
     414            return datetime_pg.date(*time.strptime(value, '%Y-%m-%d')[:3]) 
    414415        except ValueError: 
    415416            raise validators.ValidationError, gettext('Enter a valid date in YYYY-MM-DD format.') 
    416417 
     
    461462 
    462463class DateTimeField(DateField): 
    463464    def to_python(self, value): 
    464         if isinstance(value, datetime.datetime): 
     465        if isinstance(value, datetime_pg.datetime): 
    465466            return value 
    466         if isinstance(value, datetime.date): 
    467             return datetime.datetime(value.year, value.month, value.day
     467        if isinstance(value, (datetime.date, datetime.datetime)): 
     468            return datetime_pg.new_datetime_pg(value
    468469        try: # Seconds are optional, so try converting seconds first. 
    469             return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6]) 
     470            return datetime_pg.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6]) 
    470471        except ValueError: 
    471472            try: # Try without seconds. 
    472                 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5]) 
     473                return datetime_pg.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5]) 
    473474            except ValueError: # Try without hour/minutes/seconds. 
    474475                try: 
    475                     return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3]) 
     476                    return datetime_pg.datetime(*time.strptime(value, '%Y-%m-%d')[:3]) 
    476477                except ValueError: 
    477478                    raise validators.ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 
    478479 
     
    508509            d = new_data.get(date_field, None) 
    509510            t = new_data.get(time_field, None) 
    510511        if d is not None and t is not None: 
    511             return datetime.datetime.combine(d, t) 
     512            return datetime_pg.datetime.combine(d, t) 
    512513        return self.get_default() 
    513514 
    514515    def flatten_data(self,follow, obj = None): 
  • django/forms/__init__.py

    old new  
    33from django.utils.html import escape 
    44from django.conf import settings 
    55from django.utils.translation import gettext, ngettext 
     6from django.utils import datetime_pg 
    67 
    78FORM_FIELD_ID_PREFIX = 'id_' 
    89 
     
    809810        import time, datetime 
    810811        try: 
    811812            time_tuple = time.strptime(data, '%Y-%m-%d') 
    812             return datetime.date(*time_tuple[0:3]) 
     813            return datetime_pg.date(*time_tuple[0:3]) 
    813814        except (ValueError, TypeError): 
    814815            return None 
    815816    html2python = staticmethod(html2python) 
  • django/utils/datetime_pg.py

    old new  
     1# Python's datetime strftime doesn't handle dates before 1900. 
     2# These classes override date and datetime to support the formatting of a date 
     3# through its full "proleptic Gregorian" date range. 
     4# 
     5# Based on code submitted to comp.lang.python by Andrew Dalke 
     6# 
     7# >>> date_pg(1850, 8, 2).strftime("%Y/%M/%d was a %A") 
     8# '1850/08/02 was a Friday' 
     9# >>> 
     10 
     11from datetime import date as real_date, datetime as real_datetime 
     12import time 
     13import re 
     14 
     15 
     16class date_pg(real_date): 
     17    def strftime(self, fmt): 
     18        return strftime(self, fmt) 
     19date = date_pg 
     20 
     21 
     22class datetime_pg(real_datetime): 
     23    def strftime(self, fmt): 
     24        return strftime(self, fmt) 
     25    def combine(self, date, time): 
     26        return datetime_pg(date.year, date.month, date.day, time.hour, time.minute, time.microsecond, time.tzinfo) 
     27datetime = datetime_pg 
     28 
     29 
     30def new_date_pg(d): 
     31    """ Generate a date_pg from a datetime.date object """ 
     32    return date_pg(d.year, d.month, d.day) 
     33 
     34def new_datetime_pg(d): 
     35    """ Generate a datetime_pg from a datetime.date or datetime.datetime object """ 
     36    kw = [d.year, d.month, d.day] 
     37    if isinstance(d, real_datetime): 
     38        kw.extend([d.hour, d.minute, d.second, d.microsecond, d.tzinfo]) 
     39    return datetime_pg(*kw) 
     40 
     41 
     42# No support for strftime's "%s" or "%y". 
     43# Allowed if there's an even number of "%"s because they are escaped. 
     44_illegal_formatting = re.compile(r"((^|[^%])(%%)*%[sy])") 
     45 
     46def _findall(text, substr): 
     47     # Also finds overlaps 
     48     sites = [] 
     49     i = 0 
     50     while 1: 
     51         j = text.find(substr, i) 
     52         if j == -1: 
     53             break 
     54         sites.append(j) 
     55         i=j+1 
     56     return sites 
     57 
     58def strftime(dt, fmt): 
     59    if dt.year >= 1900: 
     60        return super(type(dt), dt).strftime(fmt) 
     61    illegal_formatting = _illegal_formatting.search(fmt) 
     62    if illegal_formatting: 
     63        raise TypeError("strftime of dates before 1900 does not handle" + illegal_formatting.group(0)) 
     64 
     65    year = dt.year 
     66    # For every non-leap year century, advance by 
     67    # 6 years to get into the 28-year repeat cycle 
     68    delta = 2000 - year 
     69    off = 6*(delta // 100 + delta // 400) 
     70    year = year + off 
     71 
     72    # Move to around the year 2000 
     73    year = year + ((2000 - year)//28)*28 
     74    timetuple = dt.timetuple() 
     75    s1 = time.strftime(fmt, (year,) + timetuple[1:]) 
     76    sites1 = _findall(s1, str(year)) 
     77     
     78    s2 = time.strftime(fmt, (year+28,) + timetuple[1:]) 
     79    sites2 = _findall(s2, str(year+28)) 
     80 
     81    sites = [] 
     82    for site in sites1: 
     83        if site in sites2: 
     84            sites.append(site) 
     85             
     86    s = s1 
     87    syear = "%4d" % (dt.year,) 
     88    for site in sites: 
     89        s = s[:site] + syear + s[site+4:] 
     90    return s 
  • tests/modeltests/basic/models.py

    old new  
    1919[] 
    2020 
    2121# Create an Article. 
    22 >>> from datetime import datetime 
     22>>> from django.utils.datetime_pg import datetime 
    2323>>> a = Article(id=None, headline='Area man programs in Python', pub_date=datetime(2005, 7, 28)) 
    2424 
    2525# Save it into the database. You have to call save() explicitly. 
     
    3333>>> a.headline 
    3434'Area man programs in Python' 
    3535>>> a.pub_date 
    36 datetime.datetime(2005, 7, 28, 0, 0) 
     36datetime_pg(2005, 7, 28, 0, 0) 
    3737 
    3838# Change values by changing the attributes, then calling save(). 
    3939>>> a.headline = 'Area woman programs in Python' 
     
    101101>>> a2.headline 
    102102'Second article' 
    103103>>> a2.pub_date 
    104 datetime.datetime(2005, 7, 29, 0, 0) 
     104datetime_pg(2005, 7, 29, 0, 0) 
    105105 
    106106# ...or, you can use keyword arguments. 
    107107>>> a3 = Article(id=None, headline='Third article', pub_date=datetime(2005, 7, 30)) 
     
    111111>>> a3.headline 
    112112'Third article' 
    113113>>> a3.pub_date 
    114 datetime.datetime(2005, 7, 30, 0, 0) 
     114datetime_pg(2005, 7, 30, 0, 0) 
    115115 
    116116# You can also mix and match position and keyword arguments, but be sure not to 
    117117# duplicate field information. 
     
    146146>>> a7 = Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30)) 
    147147>>> a7.save() 
    148148>>> Article.objects.get(id__exact=7).pub_date 
    149 datetime.datetime(2005, 7, 31, 12, 30) 
     149datetime_pg(2005, 7, 31, 12, 30) 
    150150 
    151151>>> a8 = Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45)) 
    152152>>> a8.save() 
    153153>>> Article.objects.get(id__exact=8).pub_date 
    154 datetime.datetime(2005, 7, 31, 12, 30, 45) 
     154datetime_pg(2005, 7, 31, 12, 30, 45) 
    155155>>> a8.id 
    1561568L 
    157157 
     
    177177 
    178178# dates() returns a list of available dates of the given scope for the given field. 
    179179>>> Article.objects.dates('pub_date', 'year') 
    180 [datetime.datetime(2005, 1, 1, 0, 0)] 
     180[datetime_pg(2005, 1, 1, 0, 0)] 
    181181>>> Article.objects.dates('pub_date', 'month') 
    182 [datetime.datetime(2005, 7, 1, 0, 0)] 
     182[datetime_pg(2005, 7, 1, 0, 0)] 
    183183>>> Article.objects.dates('pub_date', 'day') 
    184 [datetime.datetime(2005, 7, 28, 0, 0), datetime.datetime(2005, 7, 29, 0, 0), datetime.datetime(2005, 7, 30, 0, 0), datetime.datetime(2005, 7, 31, 0, 0)] 
     184[datetime_pg(2005, 7, 28, 0, 0), datetime_pg(2005, 7, 29, 0, 0), datetime_pg(2005, 7, 30, 0, 0), datetime_pg(2005, 7, 31, 0, 0)] 
    185185>>> Article.objects.dates('pub_date', 'day', order='ASC') 
    186 [datetime.datetime(2005, 7, 28, 0, 0), datetime.datetime(2005, 7, 29, 0, 0), datetime.datetime(2005, 7, 30, 0, 0), datetime.datetime(2005, 7, 31, 0, 0)] 
     186[datetime_pg(2005, 7, 28, 0, 0), datetime_pg(2005, 7, 29, 0, 0), datetime_pg(2005, 7, 30, 0, 0), datetime_pg(2005, 7, 31, 0, 0)] 
    187187>>> Article.objects.dates('pub_date', 'day', order='DESC') 
    188 [datetime.datetime(2005, 7, 31, 0, 0), datetime.datetime(2005, 7, 30, 0, 0), datetime.datetime(2005, 7, 29, 0, 0), datetime.datetime(2005, 7, 28, 0, 0)] 
     188[datetime_pg(2005, 7, 31, 0, 0), datetime_pg(2005, 7, 30, 0, 0), datetime_pg(2005, 7, 29, 0, 0), datetime_pg(2005, 7, 28, 0, 0)] 
    189189 
    190190# dates() requires valid arguments. 
    191191 
     
    213213# result one at a time, to save memory. 
    214214>>> for a in Article.objects.dates('pub_date', 'day', order='DESC').iterator(): 
    215215...     print repr(a) 
    216 datetime.datetime(2005, 7, 31, 0, 0) 
    217 datetime.datetime(2005, 7, 30, 0, 0) 
    218 datetime.datetime(2005, 7, 29, 0, 0) 
    219 datetime.datetime(2005, 7, 28, 0, 0) 
     216datetime_pg(2005, 7, 31, 0, 0) 
     217datetime_pg(2005, 7, 30, 0, 0) 
     218datetime_pg(2005, 7, 29, 0, 0) 
     219datetime_pg(2005, 7, 28, 0, 0) 
    220220 
    221221# You can combine queries with & and |. 
    222222>>> s1 = Article.objects.filter(id__exact=1) 
     
    325325>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180)) 
    326326>>> a9.save() 
    327327>>> Article.objects.get(id__exact=9).pub_date 
    328 datetime.datetime(2005, 7, 31, 12, 30, 45, 180) 
     328datetime_pg(2005, 7, 31, 12, 30, 45, 180) 
    329329""" 
    330330 
    331331if building_docs or settings.DATABASE_ENGINE == 'mysql': 
     
    335335>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180)) 
    336336>>> a9.save() 
    337337>>> Article.objects.get(id__exact=9).pub_date 
    338 datetime.datetime(2005, 7, 31, 12, 30, 45) 
     338datetime_pg(2005, 7, 31, 12, 30, 45) 
    339339""" 
    340340 
    341341__test__['API_TESTS'] += """ 
  • tests/modeltests/manipulators/models.py

    old new  
    8787>>> a2 
    8888<Album: Ultimate Ella> 
    8989>>> a2.release_date 
    90 datetime.date(2005, 2, 13) 
     90date_pg(2005, 2, 13) 
    9191"""} 
  • tests/modeltests/or_lookups/models.py

    old new  
    85853 
    8686 
    8787>>> list(Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye')).values()) 
    88 [{'headline': 'Hello and goodbye', 'pub_date': datetime.datetime(2005, 11, 29, 0, 0), 'id': 3}] 
     88[{'headline': 'Hello and goodbye', 'pub_date': datetime_pg(2005, 11, 29, 0, 0), 'id': 3}] 
    8989 
    9090>>> Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([1,2]) 
    9191{1: <Article: Hello>} 
  • tests/modeltests/reserved_names/models.py

    old new  
    4949[<Thing: a>, <Thing: h>] 
    5050 
    5151>>> Thing.objects.dates('where', 'year') 
    52 [datetime.datetime(2005, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)] 
     52[datetime_pg(2005, 1, 1, 0, 0), datetime_pg(2006, 1, 1, 0, 0)] 
    5353 
    5454>>> Thing.objects.filter(where__month=1) 
    5555[<Thing: a>] 
  • tests/modeltests/validation/models.py

    old new  
    9494>>> p.validate() 
    9595{} 
    9696>>> p.birthdate 
    97 datetime.date(2000, 5, 3) 
     97date_pg(2000, 5, 3) 
    9898 
    9999>>> p = Person(**dict(valid_params, birthdate=datetime.datetime(2000, 5, 3))) 
    100100>>> p.validate() 
    101101{} 
    102102>>> p.birthdate 
    103 datetime.date(2000, 5, 3) 
     103date_pg(2000, 5, 3) 
    104104 
    105105>>> p = Person(**dict(valid_params, birthdate='2000-05-03')) 
    106106>>> p.validate() 
    107107{} 
    108108>>> p.birthdate 
    109 datetime.date(2000, 5, 3) 
     109date_pg(2000, 5, 3) 
    110110 
    111111>>> p = Person(**dict(valid_params, birthdate='2000-5-3')) 
    112112>>> p.validate() 
    113113{} 
    114114>>> p.birthdate 
    115 datetime.date(2000, 5, 3) 
     115date_pg(2000, 5, 3) 
    116116 
    117117>>> p = Person(**dict(valid_params, birthdate='foo')) 
    118118>>> p.validate() 
     
    122122>>> p.validate() 
    123123{} 
    124124>>> p.favorite_moment 
    125 datetime.datetime(2002, 4, 3, 13, 23) 
     125datetime_pg(2002, 4, 3, 13, 23) 
    126126 
    127127>>> p = Person(**dict(valid_params, favorite_moment=datetime.datetime(2002, 4, 3))) 
    128128>>> p.validate() 
    129129{} 
    130130>>> p.favorite_moment 
    131 datetime.datetime(2002, 4, 3, 0, 0) 
     131datetime_pg(2002, 4, 3, 0, 0) 
    132132 
    133133>>> p = Person(**dict(valid_params, email='john@example.com')) 
    134134>>> p.validate() 
  • tests/regressiontests/datetime_pg/tests.py

    old new  
     1r""" 
     2>>> original_datetime(*more_recent) == datetime(*more_recent) 
     3True 
     4>>> original_datetime(*really_old) == datetime(*really_old) 
     5True 
     6>>> original_date(*more_recent) == date(*more_recent) 
     7True 
     8>>> original_date(*really_old) == date(*really_old) 
     9True 
     10 
     11>>> original_date(*just_safe).strftime('%Y-%m-%d') == date(*just_safe).strftime('%Y-%m-%d') 
     12True 
     13>>> original_datetime(*just_safe).strftime('%Y-%m-%d') == datetime(*just_safe).strftime('%Y-%m-%d') 
     14True 
     15 
     16>>> date(*just_unsafe[:3]).strftime('%Y-%m-%d (weekday %w)') 
     17'1899-12-31 (weekday 0)' 
     18>>> date(*just_safe).strftime('%Y-%m-%d (weekday %w)') 
     19'1900-01-01 (weekday 1)' 
     20 
     21>>> datetime(*just_unsafe).strftime('%Y-%m-%d %H:%M:%S (weekday %w)') 
     22'1899-12-31 23:59:59 (weekday 0)' 
     23>>> datetime(*just_safe).strftime('%Y-%m-%d %H:%M:%S (weekday %w)') 
     24'1900-01-01 00:00:00 (weekday 1)' 
     25 
     26>>> date(*just_safe).strftime('%y')   # %y will error before this date 
     27'00' 
     28>>> datetime(*just_safe).strftime('%y') 
     29'00' 
     30""" 
     31 
     32from datetime import date as original_date, datetime as original_datetime 
     33from django.utils.datetime_pg import date, datetime 
     34 
     35just_safe = (1900, 1, 1) 
     36just_unsafe = (1899, 12, 31, 23, 59, 59) 
     37really_old = (20, 1, 1) 
     38more_recent = (2006, 1, 1)