Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-42663: Support full range of allowed transition hours in zoneinfo. #23825

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

serhiy-storchaka
Copy link
Member

@serhiy-storchaka serhiy-storchaka commented Dec 17, 2020

Also refactor parsing of numbers and times (bpo-42660).

https://bugs.python.org/issue42663

#86826

Copy link
Member

@vstinner vstinner left a comment

I have no opinion on the overall approach, just some remarks on the implementation.

.hour = hour,
.minute = minute,
.second = second,
.month = Py_SAFE_DOWNCAST(month, int, uint8_t),
Copy link
Member

@vstinner vstinner Dec 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Py_SAFE_DOWNCAST() should be avoided, it is not safe in release mode: use plain cast (uint8_t)month since you just checked bounds, no?

https://bugs.python.org/issue19692

Modules/_zoneinfo.c Show resolved Hide resolved
@github-actions
Copy link

github-actions bot commented Jan 17, 2021

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale Stale PR or inactive for long period of time. label Jan 17, 2021
julian, day);
return -1;
}

if (hour < -167 || hour > 167) {
PyErr_Format(PyExc_ValueError, "Hour must be in [0, 167]");
Copy link
Member

@vstinner vstinner Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the minimum 0 or -167?

Copy link
Member Author

@serhiy-storchaka serhiy-storchaka Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The minimum of the absolute value is 0. But there may be a minus sign before time (HHH:MM:SS).

Modules/_zoneinfo.c Show resolved Hide resolved
Modules/_zoneinfo.c Show resolved Hide resolved
@@ -58,16 +58,16 @@ typedef struct {
uint8_t month;
uint8_t week;
uint8_t day;
int8_t hour;
int16_t hour;
Copy link
Member

@vstinner vstinner Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind to write a short comment explaining that hour is in range [-167; 167) (RFC ...)? Since it's non obvious why minute and second use int8_t, but hour use int16_t.

Copy link
Member

@vstinner vstinner Jan 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

167 is written in many places, it would help to avoid inconsistencies if it's updated tomorrow.

I suggested to add a comment (ex: mentioning this constant) to explain why hour requires int16_t and not int8_t, where the structure is defined.

@@ -1200,14 +1199,14 @@ calendarrule_year_to_timestamp(TransitionRuleType *base_self, int year)
}

int64_t ordinal = ymd_to_ord(year, self->month, month_day) - EPOCHORDINAL;
return ((ordinal * 86400) + (int64_t)(self->hour * 3600) +
return ((ordinal * 86400L) + (int64_t)(self->hour * 3600L) +
(int64_t)(self->minute * 60) + (int64_t)(self->second));
Copy link
Member

@vstinner vstinner Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer syntax (int64_t)var * constant, rather than trying to declare the constant as an int64_t or a long.

For example, (int64_t)self->hour * 3600 rather than (int64_t)(self->hour * 3600L).

PyErr_Format(PyExc_ValueError, "Day must be in [0, 6]");
return -1;
}

if (hour < -167 || hour > 167) {
Copy link
Member

@vstinner vstinner Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe declare a constant for this limit?

Copy link
Member Author

@serhiy-storchaka serhiy-storchaka Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think it would make code better. If it is a constant declared far from that place, somebody can change its vale without changing the type of the hour field.

if (self->julian && day >= 59 && is_leap_year(year)) {
day += 1;
}

return ((days_before_year + day) * 86400) + (self->hour * 3600) +
return ((days_before_year + day) * 86400L) + (self->hour * 3600L) +
Copy link
Member

@vstinner vstinner Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to declare constants to enhance the readability (60, 3600, 86400):

#define MIN_TO_SEC 60
#define HOUR_TO_SEC (60 * MIN_TO_SEC)
#define DAY_TO_SEC (24 * HOUR_TO_SEC)

Example of Python/pytime.c:

/* To millisecond (10^-3) */
#define SEC_TO_MS 1000

/* To microseconds (10^-6) */
#define MS_TO_US 1000
#define SEC_TO_US (SEC_TO_MS * MS_TO_US)

/* To nanoseconds (10^-9) */
#define US_TO_NS 1000
#define MS_TO_NS (MS_TO_US * US_TO_NS)
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)

/* Conversion from nanoseconds */
#define NS_TO_MS (1000 * 1000)
#define NS_TO_US (1000)

Copy link
Member Author

@serhiy-storchaka serhiy-storchaka Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constants 60 and 3600 look more readable to me than some named constant (and I have problem with distinguishing similar looking names). 86400 is enough obvious too, but if you prefer, I'll add a named constant for it.

I want to replace a trio hour/minute/second with a single integer (time offset in seconds) in future, so constants 3600 and 60 may go out here.

Copy link
Member

@vstinner vstinner left a comment

LGTM.

@serhiy-storchaka serhiy-storchaka added the type-feature A feature request or enhancement label May 6, 2022
@pganssle pganssle changed the title bpo-42663: Support full range of allowed transition hours in zipinfo. bpo-42663: Support full range of allowed transition hours in zoneinfo. May 6, 2022
@pganssle
Copy link
Member

pganssle commented May 6, 2022

I haven't had a chance to look at the changes in any detail yet, but I think this needs tests, right? Or is the mobile view obscuring them or something?

@serhiy-storchaka
Copy link
Member Author

serhiy-storchaka commented May 7, 2022

Good point. I started this PR as pure refactoring (it reduces of the C code by 67 lines), but since it also changes the behavior, it needs tests. And it happens that the Python code did not support 24h offset, and did not detect some errors, and could raise wrong type of exception.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting merge type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants