Ticket #1443: datetime_safe.diff
File datetime_safe.diff, 13.6 KB (added by , 17 years ago) |
---|
-
django/db/models/manipulators.py
9 9 from django.utils.text import capfirst 10 10 from django.utils.encoding import smart_str 11 11 from django.utils.translation import ugettext as _ 12 from django.utils import datetime_safe 12 13 13 14 def add_manipulators(sender): 14 15 cls = sender … … 332 333 pass 333 334 else: 334 335 format_string = (lookup_type == 'date') and '%B %d, %Y' or '%B %Y' 336 date_val = datetime_safe.new_datetime(date_val) 335 337 raise validators.ValidationError, "Please enter a different %s. The one you entered is already being used for %s." % \ 336 338 (from_field.verbose_name, date_val.strftime(format_string)) -
django/db/models/fields/__init__.py
20 20 from django.utils.translation import ugettext_lazy, ugettext as _ 21 21 from django.utils.encoding import smart_unicode, force_unicode, smart_str 22 22 from django.utils.maxlength import LegacyMaxlength 23 from django.utils import datetime_safe 23 24 24 25 class NOT_PROVIDED: 25 26 pass … … 530 531 if lookup_type == 'range': 531 532 value = [smart_unicode(v) for v in value] 532 533 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte') and hasattr(value, 'strftime'): 533 value = value.strftime('%Y-%m-%d')534 value = datetime_safe.new_date(value).strftime('%Y-%m-%d') 534 535 else: 535 536 value = smart_unicode(value) 536 537 return Field.get_db_prep_lookup(self, lookup_type, value) … … 562 563 # Casts dates into string format for entry into database. 563 564 if value is not None: 564 565 try: 565 value = value.strftime('%Y-%m-%d')566 value = datetime_safe.new_date(value).strftime('%Y-%m-%d') 566 567 except AttributeError: 567 568 # If value is already a string it won't have a strftime method, 568 569 # so we'll just let it pass through. … … 574 575 575 576 def flatten_data(self, follow, obj=None): 576 577 val = self._get_val_from_obj(obj) 577 return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')} 578 if val is None: 579 data = '' 580 else: 581 data = datetime_safe.new_date(val).strftime('%Y-%m-%d') 582 return {self.attname: data} 578 583 579 584 def formfield(self, **kwargs): 580 585 defaults = {'form_class': forms.DateField} … … 641 646 def flatten_data(self,follow, obj = None): 642 647 val = self._get_val_from_obj(obj) 643 648 date_field, time_field = self.get_manipulator_field_names('') 644 return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''), 645 time_field: (val is not None and val.strftime("%H:%M:%S") or '')} 649 if val is None: 650 date_data = '' 651 time_data = '' 652 else: 653 d = datetime_safe.new_datetime(val) 654 date_data = d.strftime('%Y-%m-%d') 655 time_data = d.strftime('%H:%M:%S') 656 return {date_field: date_data, time_field: time_data} 646 657 647 658 def formfield(self, **kwargs): 648 659 defaults = {'form_class': forms.DateTimeField} … … 842 853 self.path, self.match, self.recursive = path, match, recursive 843 854 kwargs['max_length'] = kwargs.get('max_length', 100) 844 855 Field.__init__(self, verbose_name, name, **kwargs) 845 856 846 857 def formfield(self, **kwargs): 847 858 defaults = { 848 859 'path': self.path, -
django/core/serializers/json.py
6 6 from django.utils import simplejson 7 7 from django.core.serializers.python import Serializer as PythonSerializer 8 8 from django.core.serializers.python import Deserializer as PythonDeserializer 9 from django.utils import datetime_safe 9 10 try: 10 11 from cStringIO import StringIO 11 12 except ImportError: … … 20 21 Convert a queryset to JSON. 21 22 """ 22 23 internal_use_only = False 23 24 24 25 def end_serialization(self): 25 26 self.options.pop('stream', None) 26 27 self.options.pop('fields', None) … … 51 52 52 53 def default(self, o): 53 54 if isinstance(o, datetime.datetime): 54 return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT)) 55 d = datetime_safe.new_datetime(o) 56 return d.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT)) 55 57 elif isinstance(o, datetime.date): 56 return o.strftime(self.DATE_FORMAT) 58 d = datetime_safe.new_date(o) 59 return d.strftime(self.DATE_FORMAT) 57 60 elif isinstance(o, datetime.time): 58 61 return o.strftime(self.TIME_FORMAT) 59 62 elif isinstance(o, decimal.Decimal): -
django/core/serializers/base.py
8 8 from StringIO import StringIO 9 9 from django.db import models 10 10 from django.utils.encoding import smart_str, smart_unicode 11 from django.utils import datetime_safe 11 12 12 13 class SerializationError(Exception): 13 14 """Something bad happened during serialization.""" … … 59 60 Convert a field's value to a string. 60 61 """ 61 62 if isinstance(field, models.DateTimeField): 62 value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S") 63 d = datetime_safe.new_datetime(getattr(obj, field.name)) 64 value = d.strftime("%Y-%m-%d %H:%M:%S") 63 65 else: 64 66 value = field.flatten_data(follow=None, obj=obj).get(field.name, "") 65 67 return smart_unicode(value) -
django/core/validators.py
141 141 # Could use time.strptime here and catch errors, but datetime.date below 142 142 # produces much friendlier error messages. 143 143 year, month, day = map(int, date_string.split('-')) 144 # This check is needed because strftime is used when saving the date145 # value to the database, and strftime requires that the year be >=1900.146 if year < 1900:147 raise ValidationError, _('Year must be 1900 or later.')148 144 try: 149 145 date(year, month, day) 150 146 except ValueError, e: … … 407 403 """ 408 404 Usage: If you create an instance of the IsPowerOf validator: 409 405 v = IsAPowerOf(2) 410 406 411 407 The following calls will succeed: 412 v(4, None) 408 v(4, None) 413 409 v(8, None) 414 410 v(16, None) 415 411 416 412 But this call: 417 413 v(17, None) 418 414 will raise "django.core.validators.ValidationError: ['This value must be a power of 2.']" -
django/utils/datetime_safe.py
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 # >>> datetime_safe.date(1850, 8, 2).strftime("%Y/%M/%d was a %A") 8 # '1850/08/02 was a Friday' 9 10 from datetime import date as real_date, datetime as real_datetime 11 import time 12 import re 13 14 15 class date(real_date): 16 def strftime(self, fmt): 17 return strftime(self, fmt) 18 19 20 class datetime(real_datetime): 21 def strftime(self, fmt): 22 return strftime(self, fmt) 23 def combine(self, date, time): 24 return datetime(date.year, date.month, date.day, time.hour, time.minute, time.microsecond, time.tzinfo) 25 def date(self): 26 return date(self.year, self.month, self.day) 27 28 29 def new_date(d): 30 """ Generate a safe date from a datetime.date object """ 31 return date(d.year, d.month, d.day) 32 33 34 def new_datetime(d): 35 """ 36 Generate a safe datetime from a datetime.date or datetime.datetime object 37 """ 38 kw = [d.year, d.month, d.day] 39 if isinstance(d, real_datetime): 40 kw.extend([d.hour, d.minute, d.second, d.microsecond, d.tzinfo]) 41 return datetime(*kw) 42 43 44 # No support for strftime's "%s" or "%y". 45 # Allowed if there's an even number of "%"s because they are escaped. 46 _illegal_formatting = re.compile(r"((^|[^%])(%%)*%[sy])") 47 48 def _findall(text, substr): 49 # Also finds overlaps 50 sites = [] 51 i = 0 52 while 1: 53 j = text.find(substr, i) 54 if j == -1: 55 break 56 sites.append(j) 57 i=j+1 58 return sites 59 60 def strftime(dt, fmt): 61 if dt.year >= 1900: 62 return super(type(dt), dt).strftime(fmt) 63 illegal_formatting = _illegal_formatting.search(fmt) 64 if illegal_formatting: 65 raise TypeError("strftime of dates before 1900 does not handle" + illegal_formatting.group(0)) 66 67 year = dt.year 68 # For every non-leap year century, advance by 69 # 6 years to get into the 28-year repeat cycle 70 delta = 2000 - year 71 off = 6*(delta // 100 + delta // 400) 72 year = year + off 73 74 # Move to around the year 2000 75 year = year + ((2000 - year)//28)*28 76 timetuple = dt.timetuple() 77 s1 = time.strftime(fmt, (year,) + timetuple[1:]) 78 sites1 = _findall(s1, str(year)) 79 80 s2 = time.strftime(fmt, (year+28,) + timetuple[1:]) 81 sites2 = _findall(s2, str(year+28)) 82 83 sites = [] 84 for site in sites1: 85 if site in sites2: 86 sites.append(site) 87 88 s = s1 89 syear = "%4d" % (dt.year,) 90 for site in sites: 91 s = s[:site] + syear + s[site+4:] 92 return s -
django/contrib/databrowse/plugins/calendars.py
8 8 from django.utils.encoding import force_unicode 9 9 from django.utils.safestring import mark_safe 10 10 from django.views.generic import date_based 11 from django.utils import datetime_safe 11 12 12 13 class CalendarPlugin(DatabrowsePlugin): 13 14 def __init__(self, field_names=None): … … 33 34 34 35 def urls(self, plugin_name, easy_instance_field): 35 36 if isinstance(easy_instance_field.field, models.DateField): 37 d = easy_instance_field.raw_value 36 38 return [mark_safe(u'%s%s/%s/%s/%s/%s/' % ( 37 39 easy_instance_field.model.url(), 38 40 plugin_name, easy_instance_field.field.name, 39 easy_instance_field.raw_value.year,40 easy_instance_field.raw_value.strftime('%b').lower(),41 easy_instance_field.raw_value.day))]41 d.year, 42 datetime_safe.new_date(d).strftime('%b').lower(), 43 d.day))] 42 44 43 45 def model_view(self, request, model_databrowse, url): 44 46 self.model, self.site = model_databrowse.model, model_databrowse.site -
django/newforms/widgets.py
15 15 from django.utils.translation import ugettext 16 16 from django.utils.encoding import StrAndUnicode, force_unicode 17 17 from django.utils.safestring import mark_safe 18 from django.utils import datetime_safe 18 19 from util import flatatt 19 20 20 21 __all__ = ( … … 170 171 if value is None: 171 172 value = '' 172 173 elif hasattr(value, 'strftime'): 174 value = datetime_safe.new_datetime(value) 173 175 value = value.strftime(self.format) 174 176 return super(DateTimeInput, self).render(name, value, attrs) 175 177 -
tests/regressiontests/datetime_safe/tests.py
1 r""" 2 >>> original_datetime(*more_recent) == datetime(*more_recent) 3 True 4 >>> original_datetime(*really_old) == datetime(*really_old) 5 True 6 >>> original_date(*more_recent) == date(*more_recent) 7 True 8 >>> original_date(*really_old) == date(*really_old) 9 True 10 11 >>> original_date(*just_safe).strftime('%Y-%m-%d') == date(*just_safe).strftime('%Y-%m-%d') 12 True 13 >>> original_datetime(*just_safe).strftime('%Y-%m-%d') == datetime(*just_safe).strftime('%Y-%m-%d') 14 True 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 32 from datetime import date as original_date, datetime as original_datetime 33 from django.utils.datetime_pg import date, datetime 34 35 just_safe = (1900, 1, 1) 36 just_unsafe = (1899, 12, 31, 23, 59, 59) 37 really_old = (20, 1, 1) 38 more_recent = (2006, 1, 1)