1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
# -*- coding: utf-8 -*-
# Copyright (c) 2025, 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:
#
# YY
# YYYY
# 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) in (2, 4):
# YY
# YYYY
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,
)
|