Skip to content

Commit

Permalink
Adjust "when" value parsing to handle YYYY-MM-DD consistently (#794)
Browse files Browse the repository at this point in the history
ISO-8601-like date formats shouldn't depend on system locale by default,
only localized formats like DD-MM-YYYY or MM-DD-YYYY.

Fixes #792.
  • Loading branch information
dbarnett authored Oct 1, 2024
1 parent fb56d20 commit 40090b9
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 15 deletions.
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v4.5.1
* Adjust "when" value parsing to handle YYYY-MM-DD consistently

v4.5.0
* Drop support for python <3.10
* Add `init` command to explicitly request auth setup/refresh
Expand Down
5 changes: 2 additions & 3 deletions gcalcli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
from .gcal import GoogleCalendarInterface
from .printer import Printer, valid_color_name
from .validators import (
get_date_input_description,
get_input,
DATE_INPUT_DESCRIPTION,
PARSABLE_DATE,
PARSABLE_DURATION,
REMINDER,
Expand Down Expand Up @@ -116,12 +116,11 @@ def run_add_prompt(parsed_args, printer):
if parsed_args.where is None:
parsed_args.where = get_input(printer, 'Location: ', STR_ALLOW_EMPTY)
if parsed_args.when is None:
date_format_desc = get_date_input_description()
parsed_args.when = get_input(
printer,
'When (? for help): ',
PARSABLE_DATE,
help=f'Expected format: {date_format_desc}',
help=f'Expected format: {DATE_INPUT_DESCRIPTION}',
)
if parsed_args.duration is None and parsed_args.end is None:
if parsed_args.allday:
Expand Down
9 changes: 7 additions & 2 deletions gcalcli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def get_times_from_duration(
return start.isoformat(), stop.isoformat()


def is_dayfirst_locale():
def _is_dayfirst_locale():
"""Detect whether system locale date format has day first.
Examples:
Expand Down Expand Up @@ -121,9 +121,14 @@ def get_time_from_str(when):
hour=0, minute=0, second=0, microsecond=0
)

# Only apply dayfirst=True if date actually starts with "XX-XX-".
# Other forms like YYYY-MM-DD shouldn't rely on locale by default (#792).
dayfirst = (
_is_dayfirst_locale() if re.match(r'^\d{1,2}-\d{1,2}-', when) else None
)
try:
event_time = dateutil_parse(
when, default=zero_oclock_today, dayfirst=is_dayfirst_locale()
when, default=zero_oclock_today, dayfirst=dayfirst
)
except ValueError:
struct, result = fuzzy_date_parse(when)
Expand Down
15 changes: 5 additions & 10 deletions gcalcli/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
get_time_from_str,
get_timedelta_from_str,
REMINDER_REGEX,
is_dayfirst_locale,
)

# TODO: in the future, pull these from the API
Expand All @@ -15,6 +14,10 @@
'banana', 'tangerine', 'peacock', 'graphite',
'blueberry', 'basil', 'tomato']

DATE_INPUT_DESCRIPTION = '\
a date (e.g. 2019-12-31, tomorrow 10am, 2nd Jan, Jan 4th, etc) or valid time \
if today'


def get_override_color_id(color):
return str(VALID_OVERRIDE_COLORS.index(color) + 1)
Expand Down Expand Up @@ -68,13 +71,6 @@ def str_to_int_validator(input_str):
)


def get_date_input_description():
dayfirst = is_dayfirst_locale()
sample_date = '2019-31-12' if dayfirst else '2019-12-31'
return f'a date (e.g. {sample_date}, tomorrow 10am, 2nd Jan, Jan 4th, etc) \
or valid time if today'


def parsable_date_validator(input_str):
"""
A filter allowing any string which can be parsed
Expand All @@ -85,9 +81,8 @@ def parsable_date_validator(input_str):
get_time_from_str(input_str)
return input_str
except ValueError:
format_desc = get_date_input_description()
raise ValidationError(
f'Expected format: {format_desc}. '
f'Expected format: {DATE_INPUT_DESCRIPTION}. '
'(Ctrl-C to exit)\n'
)

Expand Down

0 comments on commit 40090b9

Please sign in to comment.