@@ -892,3 +892,74 @@ def __repr__(self):
892892 def __str__ (self ):
893893 return "%02d:%02d:%02d.%09d" % (self .hour , self .minute ,
894894 self .second , self .nanosecond )
895+
896+
897+ class Date (object ):
898+ '''
899+ Idealized naive date: year, month, day
900+
901+ Offers wider year range than datetime.date. Dates that cannot be represented
902+ as a date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back
903+ to printing days_from_epoch offset.
904+ '''
905+
906+ MINUTE = 60
907+ HOUR = 60 * MINUTE
908+ DAY = 24 * HOUR
909+
910+ date_format = "%Y-%m-%d"
911+
912+ days_from_epoch = 0
913+
914+ def __init__ (self , value ):
915+ if isinstance (value , six .integer_types ):
916+ self .days_from_epoch = value
917+ elif isinstance (value , (datetime .date , datetime .datetime )):
918+ self ._from_timetuple (value .timetuple ())
919+ elif isinstance (value , six .string_types ):
920+ self ._from_datestring (value )
921+ else :
922+ raise TypeError ('Date arguments must be a whole number, datetime.date, or string' )
923+
924+ @property
925+ def seconds (self ):
926+ return self .days_from_epoch * Date .DAY
927+
928+ def date (self ):
929+ try :
930+ dt = datetime_from_timestamp (self .seconds )
931+ return datetime .date (dt .year , dt .month , dt .day )
932+ except Exception :
933+ raise ValueError ("%r exceeds ranges for built-in datetime.date" % self )
934+
935+ def _from_timetuple (self , t ):
936+ self .days_from_epoch = calendar .timegm (t ) // Date .DAY
937+
938+ def _from_datestring (self , s ):
939+ if s [0 ] == '+' :
940+ s = s [1 :]
941+ dt = datetime .datetime .strptime (s , self .date_format )
942+ self ._from_timetuple (dt .timetuple ())
943+
944+ def __eq__ (self , other ):
945+ if isinstance (other , Date ):
946+ return self .days_from_epoch == other .days_from_epoch
947+
948+ if isinstance (other , six .integer_types ):
949+ return self .days_from_epoch == other
950+
951+ try :
952+ return self .date == other
953+ except Exception :
954+ return False
955+
956+ def __repr__ (self ):
957+ return "Date(%s)" % self .days_from_epoch
958+
959+ def __str__ (self ):
960+ try :
961+ dt = datetime_from_timestamp (self .seconds )
962+ return "%04d-%02d-%02d" % (dt .year , dt .month , dt .day )
963+ except :
964+ # If we overflow datetime.[MIN|M
965+ return str (self .days_from_epoch )
0 commit comments