You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.4 KiB
162 lines
4.4 KiB
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright (c) 2021, Brandon Nielsen
|
|
# All rights reserved.
|
|
#
|
|
# This software may be modified and distributed under the terms
|
|
# of the BSD license. See the LICENSE file for details.
|
|
|
|
from aniso8601.builders import TupleBuilder
|
|
from aniso8601.builders.python import PythonTimeBuilder
|
|
from aniso8601.compat import is_string
|
|
from aniso8601.exceptions import ISOFormatError
|
|
from aniso8601.resolution import DateResolution
|
|
|
|
|
|
def get_date_resolution(isodatestr):
|
|
# Valid string formats are:
|
|
#
|
|
# Y[YYY]
|
|
# YYYY-MM-DD
|
|
# YYYYMMDD
|
|
# YYYY-MM
|
|
# YYYY-Www
|
|
# YYYYWww
|
|
# YYYY-Www-D
|
|
# YYYYWwwD
|
|
# YYYY-DDD
|
|
# YYYYDDD
|
|
isodatetuple = parse_date(isodatestr, builder=TupleBuilder)
|
|
|
|
if isodatetuple.DDD is not None:
|
|
# YYYY-DDD
|
|
# YYYYDDD
|
|
return DateResolution.Ordinal
|
|
|
|
if isodatetuple.D is not None:
|
|
# YYYY-Www-D
|
|
# YYYYWwwD
|
|
return DateResolution.Weekday
|
|
|
|
if isodatetuple.Www is not None:
|
|
# YYYY-Www
|
|
# YYYYWww
|
|
return DateResolution.Week
|
|
|
|
if isodatetuple.DD is not None:
|
|
# YYYY-MM-DD
|
|
# YYYYMMDD
|
|
return DateResolution.Day
|
|
|
|
if isodatetuple.MM is not None:
|
|
# YYYY-MM
|
|
return DateResolution.Month
|
|
|
|
# Y[YYY]
|
|
return DateResolution.Year
|
|
|
|
|
|
def parse_date(isodatestr, builder=PythonTimeBuilder):
|
|
# Given a string in any ISO 8601 date format, return a datetime.date
|
|
# object that corresponds to the given date. Valid string formats are:
|
|
#
|
|
# Y[YYY]
|
|
# YYYY-MM-DD
|
|
# YYYYMMDD
|
|
# YYYY-MM
|
|
# YYYY-Www
|
|
# YYYYWww
|
|
# YYYY-Www-D
|
|
# YYYYWwwD
|
|
# YYYY-DDD
|
|
# YYYYDDD
|
|
if is_string(isodatestr) is False:
|
|
raise ValueError("Date must be string.")
|
|
|
|
if isodatestr.startswith("+") or isodatestr.startswith("-"):
|
|
raise NotImplementedError(
|
|
"ISO 8601 extended year representation " "not supported."
|
|
)
|
|
|
|
if len(isodatestr) == 0 or isodatestr.count("-") > 2:
|
|
raise ISOFormatError('"{0}" is not a valid ISO 8601 date.'.format(isodatestr))
|
|
yearstr = None
|
|
monthstr = None
|
|
daystr = None
|
|
weekstr = None
|
|
weekdaystr = None
|
|
ordinaldaystr = None
|
|
|
|
if len(isodatestr) <= 4:
|
|
# Y[YYY]
|
|
yearstr = isodatestr
|
|
elif "W" in isodatestr:
|
|
if len(isodatestr) == 10:
|
|
# YYYY-Www-D
|
|
yearstr = isodatestr[0:4]
|
|
weekstr = isodatestr[6:8]
|
|
weekdaystr = isodatestr[9]
|
|
elif len(isodatestr) == 8:
|
|
if "-" in isodatestr:
|
|
# YYYY-Www
|
|
yearstr = isodatestr[0:4]
|
|
weekstr = isodatestr[6:]
|
|
else:
|
|
# YYYYWwwD
|
|
yearstr = isodatestr[0:4]
|
|
weekstr = isodatestr[5:7]
|
|
weekdaystr = isodatestr[7]
|
|
elif len(isodatestr) == 7:
|
|
# YYYYWww
|
|
yearstr = isodatestr[0:4]
|
|
weekstr = isodatestr[5:]
|
|
elif len(isodatestr) == 7:
|
|
if "-" in isodatestr:
|
|
# YYYY-MM
|
|
yearstr = isodatestr[0:4]
|
|
monthstr = isodatestr[5:]
|
|
else:
|
|
# YYYYDDD
|
|
yearstr = isodatestr[0:4]
|
|
ordinaldaystr = isodatestr[4:]
|
|
elif len(isodatestr) == 8:
|
|
if "-" in isodatestr:
|
|
# YYYY-DDD
|
|
yearstr = isodatestr[0:4]
|
|
ordinaldaystr = isodatestr[5:]
|
|
else:
|
|
# YYYYMMDD
|
|
yearstr = isodatestr[0:4]
|
|
monthstr = isodatestr[4:6]
|
|
daystr = isodatestr[6:]
|
|
elif len(isodatestr) == 10:
|
|
# YYYY-MM-DD
|
|
yearstr = isodatestr[0:4]
|
|
monthstr = isodatestr[5:7]
|
|
daystr = isodatestr[8:]
|
|
else:
|
|
raise ISOFormatError('"{0}" is not a valid ISO 8601 date.'.format(isodatestr))
|
|
|
|
hascomponent = False
|
|
|
|
for componentstr in [yearstr, monthstr, daystr, weekstr, weekdaystr, ordinaldaystr]:
|
|
if componentstr is not None:
|
|
hascomponent = True
|
|
|
|
if componentstr.isdigit() is False:
|
|
raise ISOFormatError(
|
|
'"{0}" is not a valid ISO 8601 date.'.format(isodatestr)
|
|
)
|
|
|
|
if hascomponent is False:
|
|
raise ISOFormatError('"{0}" is not a valid ISO 8601 date.'.format(isodatestr))
|
|
|
|
return builder.build_date(
|
|
YYYY=yearstr,
|
|
MM=monthstr,
|
|
DD=daystr,
|
|
Www=weekstr,
|
|
D=weekdaystr,
|
|
DDD=ordinaldaystr,
|
|
)
|