LdapServer : add naive parameter to parse/format datetime/date helper functions

This commit is contained in:
Benjamin Renard 2019-09-30 12:25:58 +02:00
parent 86b99b69a7
commit f5659cb481

View file

@ -153,7 +153,7 @@ class LdapServerException(BaseException):
# #
# Helpers # Helpers
# #
def parse_datetime(value, to_timezone=None, default_timezone=None): def parse_datetime(value, to_timezone=None, default_timezone=None, naive=None):
""" """
Convert LDAP date string to datetime.datetime object Convert LDAP date string to datetime.datetime object
@ -162,11 +162,14 @@ def parse_datetime(value, to_timezone=None, default_timezone=None):
specific timezone (optional, default : timezone of the LDAP date string) specific timezone (optional, default : timezone of the LDAP date string)
:param default_timezone: The timezone used if LDAP date string does not specified :param default_timezone: The timezone used if LDAP date string does not specified
the timezone (optional, default : server local timezone) the timezone (optional, default : server local timezone)
:param naive: Use naive datetime : return naive datetime object (without timezone conversion from LDAP)
""" """
assert to_timezone is None or isinstance(to_timezone, datetime.tzinfo) or isinstance(to_timezone, str), 'to_timezone must be None, a datetime.tzinfo object or a string (not %s)' % type(to_timezone) assert to_timezone is None or isinstance(to_timezone, datetime.tzinfo) or isinstance(to_timezone, str), 'to_timezone must be None, a datetime.tzinfo object or a string (not %s)' % type(to_timezone)
assert default_timezone is None or isinstance(default_timezone, datetime.tzinfo) or isinstance(default_timezone, pytz.tzinfo.DstTzInfo) or isinstance(default_timezone, str), 'default_timezone parameter must be None, a string, a pytz.tzinfo.DstTzInfo or a datetime.tzinfo object (not %s)' % type(default_timezone) assert default_timezone is None or isinstance(default_timezone, datetime.tzinfo) or isinstance(default_timezone, pytz.tzinfo.DstTzInfo) or isinstance(default_timezone, str), 'default_timezone parameter must be None, a string, a pytz.tzinfo.DstTzInfo or a datetime.tzinfo object (not %s)' % type(default_timezone)
date = dateutil.parser.parse(value, dayfirst=False) date = dateutil.parser.parse(value, dayfirst=False)
if not date.tzinfo: if not date.tzinfo:
if naive:
return date
if not default_timezone: if not default_timezone:
default_timezone = pytz.utc default_timezone = pytz.utc
elif isinstance(default_timezone, str): elif isinstance(default_timezone, str):
@ -177,13 +180,15 @@ def parse_datetime(value, to_timezone=None, default_timezone=None):
date = date.replace(tzinfo=default_timezone) date = date.replace(tzinfo=default_timezone)
else: else:
raise Exception("It's not supposed to happen!") raise Exception("It's not supposed to happen!")
elif naive:
return date.replace(tzinfo=None)
if to_timezone: if to_timezone:
if isinstance(to_timezone, str): if isinstance(to_timezone, str):
to_timezone = pytz.timezone(to_timezone) to_timezone = pytz.timezone(to_timezone)
return date.astimezone(to_timezone) return date.astimezone(to_timezone)
return date return date
def parse_date(value, to_timezone=None, default_timezone=None): def parse_date(value, to_timezone=None, default_timezone=None, naive=None):
""" """
Convert LDAP date string to datetime.date object Convert LDAP date string to datetime.date object
@ -192,10 +197,11 @@ def parse_date(value, to_timezone=None, default_timezone=None):
specific timezone (optional, default : timezone of the LDAP date string) specific timezone (optional, default : timezone of the LDAP date string)
:param default_timezone: The timezone used if LDAP date string does not specified :param default_timezone: The timezone used if LDAP date string does not specified
the timezone (optional, default : server local timezone) the timezone (optional, default : server local timezone)
:param naive: Use naive datetime : do not handle timezone conversion from LDAP
""" """
return parse_datetime(value, to_timezone, default_timezone).date() return parse_datetime(value, to_timezone, default_timezone, naive).date()
def format_datetime(value, from_timezone=None, to_timezone=None): def format_datetime(value, from_timezone=None, to_timezone=None, naive=None):
""" """
Convert datetime.datetime object to LDAP date string Convert datetime.datetime object to LDAP date string
@ -203,11 +209,12 @@ def format_datetime(value, from_timezone=None, to_timezone=None):
:param from_timezone: The timezone used if datetime.datetime object is naive (no tzinfo) :param from_timezone: The timezone used if datetime.datetime object is naive (no tzinfo)
(optional, default : server local timezone) (optional, default : server local timezone)
:param to_timezone: The timezone used in LDAP (optional, default : UTC) :param to_timezone: The timezone used in LDAP (optional, default : UTC)
:param naive: Use naive datetime : datetime store as UTC in LDAP (without conversion)
""" """
assert isinstance(value, datetime.datetime), 'First parameter must be an datetime.datetime object (not %s)' % type(value) assert isinstance(value, datetime.datetime), 'First parameter must be an datetime.datetime object (not %s)' % type(value)
assert from_timezone is None or isinstance(from_timezone, datetime.tzinfo) or isinstance(from_timezone, pytz.tzinfo.DstTzInfo) or isinstance(from_timezone, str), 'from_timezone parameter must be None, a string, a pytz.tzinfo.DstTzInfo or a datetime.tzinfo object (not %s)' % type(from_timezone) assert from_timezone is None or isinstance(from_timezone, datetime.tzinfo) or isinstance(from_timezone, pytz.tzinfo.DstTzInfo) or isinstance(from_timezone, str), 'from_timezone parameter must be None, a string, a pytz.tzinfo.DstTzInfo or a datetime.tzinfo object (not %s)' % type(from_timezone)
assert to_timezone is None or isinstance(to_timezone, datetime.tzinfo) or isinstance(to_timezone, str), 'to_timezone must be None, a datetime.tzinfo object or a string (not %s)' % type(to_timezone) assert to_timezone is None or isinstance(to_timezone, datetime.tzinfo) or isinstance(to_timezone, str), 'to_timezone must be None, a datetime.tzinfo object or a string (not %s)' % type(to_timezone)
if not value.tzinfo: if not value.tzinfo and not naive:
if not from_timezone: if not from_timezone:
from_timezone = dateutil.tz.tzlocal() from_timezone = dateutil.tz.tzlocal()
elif isinstance(from_timezone, str): elif isinstance(from_timezone, str):
@ -218,6 +225,8 @@ def format_datetime(value, from_timezone=None, to_timezone=None):
from_value = value.replace(tzinfo=from_timezone) from_value = value.replace(tzinfo=from_timezone)
else: else:
raise Exception("It's not supposed to happen!") raise Exception("It's not supposed to happen!")
elif naive:
from_value = value.replace(tzinfo=pytz.utc)
else: else:
from_value = copy.deepcopy(value) from_value = copy.deepcopy(value)
if not to_timezone: if not to_timezone:
@ -230,7 +239,7 @@ def format_datetime(value, from_timezone=None, to_timezone=None):
datestring = datestring.replace('+0000', 'Z') datestring = datestring.replace('+0000', 'Z')
return datestring return datestring
def format_date(value, from_timezone=None, to_timezone=None): def format_date(value, from_timezone=None, to_timezone=None, naive=None):
""" """
Convert datetime.date object to LDAP date string Convert datetime.date object to LDAP date string
@ -238,15 +247,17 @@ def format_date(value, from_timezone=None, to_timezone=None):
:param from_timezone: The timezone used if datetime.datetime object is naive (no tzinfo) :param from_timezone: The timezone used if datetime.datetime object is naive (no tzinfo)
(optional, default : server local timezone) (optional, default : server local timezone)
:param to_timezone: The timezone used in LDAP (optional, default : UTC) :param to_timezone: The timezone used in LDAP (optional, default : UTC)
:param naive: Use naive datetime : do not handle timezone conversion before formating
and return datetime as UTC (because LDAP required a timezone)
""" """
assert isinstance(value, datetime.date), 'First parameter must be an datetime.date object (not %s)' % type(value) assert isinstance(value, datetime.date), 'First parameter must be an datetime.date object (not %s)' % type(value)
return format_datetime(datetime.datetime.combine(value, datetime.datetime.min.time()), from_timezone, to_timezone) return format_datetime(datetime.datetime.combine(value, datetime.datetime.min.time()), from_timezone, to_timezone, naive)
# #
# Tests # Tests
# #
if __name__ == '__main__': if __name__ == '__main__':
now = datetime.datetime.now() now = datetime.datetime.now().replace(tzinfo=dateutil.tz.tzlocal())
print "Now = %s" % now print "Now = %s" % now
datestring_now = format_datetime(now) datestring_now = format_datetime(now)
@ -257,6 +268,7 @@ if __name__ == '__main__':
print "format_datetime (to_timezone=utc) : %s" % format_datetime(now, to_timezone=pytz.utc) print "format_datetime (to_timezone=utc) : %s" % format_datetime(now, to_timezone=pytz.utc)
print "format_datetime (to_timezone=local) : %s" % format_datetime(now, to_timezone=dateutil.tz.tzlocal()) print "format_datetime (to_timezone=local) : %s" % format_datetime(now, to_timezone=dateutil.tz.tzlocal())
print "format_datetime (to_timezone=Tokyo) : %s" % format_datetime(now, to_timezone='Asia/Tokyo') print "format_datetime (to_timezone=Tokyo) : %s" % format_datetime(now, to_timezone='Asia/Tokyo')
print "format_datetime (naive=True) : %s" % format_datetime(now, naive=True)
print "format_date : %s" % format_date(now) print "format_date : %s" % format_date(now)
print "format_date (from_timezone=utc) : %s" % format_date(now.replace(tzinfo=None), from_timezone=pytz.utc) print "format_date (from_timezone=utc) : %s" % format_date(now.replace(tzinfo=None), from_timezone=pytz.utc)
@ -265,6 +277,7 @@ if __name__ == '__main__':
print "format_date (to_timezone=utc) : %s" % format_date(now, to_timezone=pytz.utc) print "format_date (to_timezone=utc) : %s" % format_date(now, to_timezone=pytz.utc)
print "format_date (to_timezone=local) : %s" % format_date(now, to_timezone=dateutil.tz.tzlocal()) print "format_date (to_timezone=local) : %s" % format_date(now, to_timezone=dateutil.tz.tzlocal())
print "format_date (to_timezone=Tokyo) : %s" % format_date(now, to_timezone='Asia/Tokyo') print "format_date (to_timezone=Tokyo) : %s" % format_date(now, to_timezone='Asia/Tokyo')
print "format_date (naive=True) : %s" % format_date(now, naive=True)
print "parse_datetime : %s" % parse_datetime(datestring_now) print "parse_datetime : %s" % parse_datetime(datestring_now)
@ -274,6 +287,7 @@ if __name__ == '__main__':
print "parse_datetime (to_timezone=utc) : %s" % parse_datetime(datestring_now, to_timezone=pytz.utc) print "parse_datetime (to_timezone=utc) : %s" % parse_datetime(datestring_now, to_timezone=pytz.utc)
print "parse_datetime (to_timezone=local) : %s" % parse_datetime(datestring_now, to_timezone=dateutil.tz.tzlocal()) print "parse_datetime (to_timezone=local) : %s" % parse_datetime(datestring_now, to_timezone=dateutil.tz.tzlocal())
print "parse_datetime (to_timezone=Tokyo) : %s" % parse_datetime(datestring_now, to_timezone='Asia/Tokyo') print "parse_datetime (to_timezone=Tokyo) : %s" % parse_datetime(datestring_now, to_timezone='Asia/Tokyo')
print "parse_datetime (naive=True) : %s" % parse_datetime(datestring_now, naive=True)
print "parse_date : %s" % parse_date(datestring_now) print "parse_date : %s" % parse_date(datestring_now)
print "parse_date (default_timezone=utc) : %s" % parse_date(datestring_now[0:-1], default_timezone=pytz.utc) print "parse_date (default_timezone=utc) : %s" % parse_date(datestring_now[0:-1], default_timezone=pytz.utc)
@ -282,3 +296,4 @@ if __name__ == '__main__':
print "parse_date (to_timezone=utc) : %s" % parse_date(datestring_now, to_timezone=pytz.utc) print "parse_date (to_timezone=utc) : %s" % parse_date(datestring_now, to_timezone=pytz.utc)
print "parse_date (to_timezone=local) : %s" % parse_date(datestring_now, to_timezone=dateutil.tz.tzlocal()) print "parse_date (to_timezone=local) : %s" % parse_date(datestring_now, to_timezone=dateutil.tz.tzlocal())
print "parse_date (to_timezone=Tokyo) : %s" % parse_date(datestring_now, to_timezone='Asia/Tokyo') print "parse_date (to_timezone=Tokyo) : %s" % parse_date(datestring_now, to_timezone='Asia/Tokyo')
print "parse_date (naive=True) : %s" % parse_date(datestring_now, naive=True)