Updated to pytimeparse2, added tests for custom Click param types
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
import datetime
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
import bitmath
|
||||
import click
|
||||
import pytimeparse
|
||||
import pytimeparse2
|
||||
|
||||
from osxphotos.export_db_utils import export_db_get_version
|
||||
from osxphotos.photoinfo import PhotoInfoNone
|
||||
@@ -159,19 +160,31 @@ class DateOffset(click.ParamType):
|
||||
name = "DATEOFFSET"
|
||||
|
||||
def convert(self, value, param, ctx):
|
||||
offset = pytimeparse.parse(value)
|
||||
# if it's a single number treat it as days
|
||||
# but pytimeparse2 treats is as seconds so need to verify it's just a number and if so,
|
||||
# convert it to seconds
|
||||
value = value.strip()
|
||||
if re.match(r"^[+-]?\s*?\d+$", value):
|
||||
# just a number
|
||||
# strip any whitespace, e.g. for "+ 1" or "- 1"
|
||||
value = "".join(value.split())
|
||||
try:
|
||||
return datetime.timedelta(days=int(value))
|
||||
except ValueError:
|
||||
self.fail(
|
||||
f"Invalid date offset format: {value}. "
|
||||
"Valid format for date/time offset: '±D days', '±W weeks', '±M months', '±D' where D is days "
|
||||
)
|
||||
|
||||
offset = pytimeparse2.parse(value)
|
||||
if offset is not None:
|
||||
offset = offset / 86400
|
||||
return datetime.timedelta(days=offset)
|
||||
|
||||
# could be in format "-1" (negative offset) or "+1" (positive offset)
|
||||
try:
|
||||
return datetime.timedelta(days=int(value))
|
||||
except ValueError:
|
||||
self.fail(
|
||||
f"Invalid date offset format: {value}. "
|
||||
"Valid format for date/time offset: '±D days', '±W weeks', '±D' where D is days "
|
||||
)
|
||||
self.fail(
|
||||
f"Invalid date offset format: {value}. "
|
||||
"Valid format for date/time offset: '±D days', '±W weeks', '±M months', '±D' where D is days "
|
||||
)
|
||||
|
||||
|
||||
class TimeOffset(click.ParamType):
|
||||
@@ -180,18 +193,14 @@ class TimeOffset(click.ParamType):
|
||||
name = "TIMEOFFSET"
|
||||
|
||||
def convert(self, value, param, ctx):
|
||||
offset = pytimeparse.parse(value)
|
||||
offset = pytimeparse2.parse(value)
|
||||
if offset is not None:
|
||||
return datetime.timedelta(seconds=offset)
|
||||
|
||||
# could be in format "-18000" (negative offset) or "+18000" (positive offset)
|
||||
try:
|
||||
return datetime.timedelta(seconds=int(value))
|
||||
except ValueError:
|
||||
self.fail(
|
||||
f"Invalid time offset format: {value}. "
|
||||
"Valid format for date/time offset: '±HH:MM:SS', '±H hours' (or hr), '±M minutes' (or min), '±S seconds' (or sec), '±S' (where S is seconds)"
|
||||
)
|
||||
self.fail(
|
||||
f"Invalid time offset format: {value}. "
|
||||
"Valid format for date/time offset: '±HH:MM:SS', '±H hours' (or hr), '±M minutes' (or min), '±S seconds' (or sec), '±S' (where S is seconds)"
|
||||
)
|
||||
|
||||
|
||||
class UTCOffset(click.ParamType):
|
||||
|
||||
@@ -8,7 +8,7 @@ import re
|
||||
|
||||
def utc_offset_string_to_seconds(utc_offset: str) -> int:
|
||||
"""match a UTC offset in format ±[hh]:[mm], ±[h]:[mm], or ±[hh][mm] and return number of seconds offset"""
|
||||
patterns = ["^([+-]?)(\d{1,2}):(\d{2})$", "^([+-]?)(\d{2})(\d{2})$"]
|
||||
patterns = [r"^([+-]?)(\d{1,2}):(\d{2})$", r"^([+-]?)(\d{2})(\d{2})$"]
|
||||
for pattern in patterns:
|
||||
match = re.match(pattern, utc_offset)
|
||||
if not match:
|
||||
@@ -56,7 +56,7 @@ def update_datetime(
|
||||
return dt
|
||||
|
||||
|
||||
def time_string_to_datetime(time: str) -> datetime.datetime:
|
||||
def time_string_to_datetime(time: str) -> datetime.time:
|
||||
"""Convert time string to datetime.datetime"""
|
||||
|
||||
""" valid time formats:
|
||||
@@ -74,7 +74,7 @@ def time_string_to_datetime(time: str) -> datetime.datetime:
|
||||
|
||||
for dt_format in time_formats:
|
||||
try:
|
||||
parsed_dt = datetime.datetime.strptime(time, dt_format)
|
||||
parsed_dt = datetime.datetime.strptime(time, dt_format).time()
|
||||
except ValueError as e:
|
||||
pass
|
||||
else:
|
||||
|
||||
@@ -54,3 +54,8 @@ class Timezone:
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Timezone):
|
||||
return self.timezone == other.timezone
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user