@BlackJack
Ich habe eine eigene `DateTime` Klasse, die sich letzten Endes wie ein `datetime` Objekt verhalten soll allerdings zusätzlich noch ein paar Methoden und eine eigene `__format__` Methode hat. Ich möchte nicht von `datetime` erben, da ich beim Addieren und Subtrahieren wiederum keine `datetime`- sondern `DateTime`-Objekte zurückbekommen möchte. Bisher schaut das ganze so aus:
Code: Alles auswählen
class DateTime(object):
def __init__(self, dt_values, dawn=None):
'''__init__(dt_values[, dawn])
__init__(DateTime)
The given argument(s) must be either a tuple/list
and/or `dawn` which must be True or False or a
`DateTime` instance in which case a copy of the
same will be created.
If `dt_values` only has 3 elements for year, month
and date the `dawn` flag must be given otherwise a
ValueError occurs. This flag indicates whether the
`DateTime` instance become time values of (0, 0) if
`dawn` is True or (23, 59) if False. In both cases
the `has_time` flag of the instance will be False.
If `dt_values` has 5 elements this values will be
used to create the datetime. Thereby no `dawn` is
needed.
If `dt_values` has more or less than 3 or 5 elements
a ValueError occurs. '''
if not isinstance(dt_values, DateTime):
if len(dt_values) == 3:
if dawn is None:
raise ValueError('Can\'t create a {!r} instance '
'without time values and missing '
'`dawn` flag.'.format(
self.__class__.__name__))
hour, minute = (0, 0) if dawn else (23, 59)
self._datetime = datetime.datetime(*dt_values,
hour=hour, minute=minute)
self.has_time = False
elif len(dt_values) == 5:
self._datetime = datetime.datetime(*dt_values)
self.has_time = True
else:
raise ValueError('Wrong argument amount to create '
'{0!r} instance: {1!r}'.format(
self.__class__.__name__, dt_values))
else:
self._datetime = dt_values._datetime
self.has_time = dt_values.has_time
@property
def hour(self):
return self._datetime.hour
@property
def minute(self):
return self._datetime.minute
@property
def day(self):
return self._datetime.day
@property
def month(self):
return self._datetime.month
@property
def year(self):
return self._datetime.year
@classmethod
def now(cls, time=None):
if time is None:
return cls(*datetime.datetime.now().timetuple()[0:5])
return cls(
*datetime.datetime.now().timetuple()[0:3] +
((0, 0) if time == 'start' else (23, 59)),
has_time = False
)
def replace(self, **kwargs):
new = DateTime(self)
new._datetime = new._datetime.replace(**kwargs)
new.has_date = True
return new
def timetuple(self):
return self._datetime.timetuple()
def weekday(self):
'''weekday() -> Bundle object
Returns a bundle object which contains these attributes:
`weekday`: Weekday as number (0=Mo - 6=Su)
`position`: The number of the weekday within
month (1 - 5)
`is_last`: Is it the last occurence of the
weekday within month (True/False) '''
return utils.Bundle(
position=((self.day - 1) / 7) + 1,
is_last=(utils.month_len(self) - self.day) < 7,
weekday=self._datetime.weekday()
)
def get_raws(self):
return {'YmdHM': self.timetuple()[0:5], 'has_time': self.has_time}
def _validate_delta(self, delta):
if delta.seconds + delta.microseconds:
raise NotImplementedError(
'Counting with time values leading to non day exactly '
'resolution currently not implemented.'
)
def __add__(self, delta):
self._validate_delta(delta)
new = DateTime(self)
new._datetime = new._datetime + delta
return new
def __sub__(self, value):
if isinstance(value, datetime.timedelta):
self._validate_delta(value)
new = DateTime(self)
new._datetime = new._datetime - value
return new
return self._datetime - value._datetime
def __lt__(self, other):
return self._datetime < other._datetime
def __le__(self, other):
return self._datetime <= other._datetime
def __gt__(self, other):
return self._datetime > other._datetime
def __ge__(self, other):
return self._datetime >= other._datetime
def __eq__(self, other):
return self._datetime == other._datetime
def __ne__(self, other):
return self._datetime != other._datetime
def __format__(self, spec):
#Needed, cause datetime's strftime()-method
#has the following year-restrictions:
# < Python 3.1 year >= 1900 is required
# <= Python 3.2 year >= 1000 is required
# >= Python 3.3 no restriction
try:
return format(self._datetime, spec)
except ValueError:
for directive, value in zip(
(('%Y', '{:04d}'), ('%m', '{:02d}'), ('%d', '{:02d}'),
('%H', '{:02d}'), ('%M', '{:02d}')),
self._datetime.timetuple()[0:5]):
spec = spec.replace(directive[0], directive[1].format(value))
return spec
def __hash__(self):
return hash((self._datetime, self.has_time))
def __str__(self):
def_time = ('', '') if self.has_time else ('[', ']')
return ('{0:%Y-%m-%d '
'{def_time[0]}%H:%M{def_time[1]}}'.format(
self, def_time=def_time))
def __repr__(self):
def_time = ('', '') if self.has_time else ('[', ']')
return ('{0}.{1}({2:%Y-%m-%d '
'{def_time[0]}%H:%M{def_time[1]}})'.format(
self.__module__, self.__class__.__name__, self,
def_time=def_time))
Nun dachte ich mir eben, dass die ganzen `__eq__`, `__ne__`, `@property: year` etc. Definitionen wegfallen könnten, wenn ich einfach erstmal gewünschte Attribute auf `self._datetime` abfrage. Wenn eine Methode oder ein Attribut dort nicht gefunden wird, schaue ich auf `self` nach oder löse dann eine Exception aus.
mutetella