[unhandled exception parsing "future dates" in some locales]

There is already a check in the MonitoredDate class for years
which are more than one year in the future, so such a date is
already going to be shown in red.

But some locales use the "datetime" library to parse typed-in
dates and that has a maximum year of datetime.MAXYEAR, 9999
currently, so dates greater than that produce a ValueError.

Besides adding checks for that, I have also made it so that
locales which don't need that library don't use it.

Fixes #10815
This commit is contained in:
Paul Franklin 2018-09-26 14:04:52 -07:00
parent 2490e2d07d
commit cc7e4fda85
2 changed files with 19 additions and 12 deletions

View File

@ -186,7 +186,8 @@ class DateDisplayIs(DateDisplay):
text, scal) text, scal)
def _get_weekday(self, date_val): def _get_weekday(self, date_val):
if date_val[0] == 0 or date_val[1] == 0: # no day or no month or both if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both
or date_val[2] > datetime.MAXYEAR): # bug 10815
return '' return ''
w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d
return self.short_days[((w_day.weekday() + 1) % 7) + 1] return self.short_days[((w_day.weekday() + 1) % 7) + 1]

View File

@ -4,7 +4,7 @@
# #
# Copyright (C) 2004-2006 Donald N. Allingham # Copyright (C) 2004-2006 Donald N. Allingham
# Copyright (C) 2013 Vassilii Khachaturov # Copyright (C) 2013 Vassilii Khachaturov
# Copyright (C) 2014-2017 Paul Franklin # Copyright (C) 2014-2018 Paul Franklin
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -570,6 +570,7 @@ class DateDisplay:
def _get_short_weekday(self, date_val): def _get_short_weekday(self, date_val):
if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both
or date_val[1] == 13 # Hebrew has 13 months or date_val[1] == 13 # Hebrew has 13 months
or date_val[2] > datetime.MAXYEAR # bug 10815
or date_val[2] < 0): # B.C.E. date or date_val[2] < 0): # B.C.E. date
return '' return ''
w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d
@ -578,6 +579,7 @@ class DateDisplay:
def _get_long_weekday(self, date_val): def _get_long_weekday(self, date_val):
if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both
or date_val[1] == 13 # Hebrew has 13 months or date_val[1] == 13 # Hebrew has 13 months
or date_val[2] > datetime.MAXYEAR # bug 10815
or date_val[2] < 0): # B.C.E. date or date_val[2] < 0): # B.C.E. date
return '' return ''
w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d
@ -597,16 +599,20 @@ class DateDisplay:
return str(date_val[2]) return str(date_val[2])
else: else:
value = self.dhformat.replace('%m', str(date_val[1])) value = self.dhformat.replace('%m', str(date_val[1]))
# some locales have %b for the month, e.g. ar_EG, is_IS, nb_NO if '%b' in value or '%B' in value:
# so it would be "Jan" but as it's "numeric" I'll make it "1" # some locales have %b for the month (ar_EG, is_IS, nb_NO)
# so it would be "Jan" but as it's "numeric" make it "1"
value = value.replace('%b', str(date_val[1])) value = value.replace('%b', str(date_val[1]))
# some locales have %B for the month, e.g. ta_IN # some locales have %B for the month, e.g. ta_IN
# so it would be "January" but as it's "numeric" I'll make it 1 # so it would be "January" but as it's "numeric" make it 1
value = value.replace('%B', str(date_val[1])) value = value.replace('%B', str(date_val[1]))
if '%a' in value or '%A' in value:
# some locales have %a for the abbreviated day, e.g. is_IS # some locales have %a for the abbreviated day, e.g. is_IS
value = value.replace('%a', self._get_short_weekday(date_val)) value = value.replace('%a',
self._get_short_weekday(date_val))
# some locales have %A for the long/full day, e.g. ta_IN # some locales have %A for the long/full day, e.g. ta_IN
value = value.replace('%A', self._get_long_weekday(date_val)) value = value.replace('%A',
self._get_long_weekday(date_val))
if date_val[0] == 0: # ignore the zero day and its delimiter if date_val[0] == 0: # ignore the zero day and its delimiter
i_day = value.find('%d') i_day = value.find('%d')
if len(value) == i_day + 2: # delimiter is left of the day if len(value) == i_day + 2: # delimiter is left of the day