Skip to content

Refactor time parsing with thread-safe localtime and leap year fix#4692

Merged
rouault merged 1 commit intoOSGeo:masterfrom
KinshukSS2:fix/localtime-thread-safety-and-leap-year
Mar 5, 2026
Merged

Refactor time parsing with thread-safe localtime and leap year fix#4692
rouault merged 1 commit intoOSGeo:masterfrom
KinshukSS2:fix/localtime-thread-safety-and-leap-year

Conversation

@KinshukSS2
Copy link
Contributor

replace non-thread-safe localtime() with localtime_r() (POSIX) / localtime_s() (Windows) in hgridshift and vgridshift +t_final=now handling.

also fix leap year calculation: use 366 days for leap years instead of hardcoded 365.

Closes #4691

@KinshukSS2 KinshukSS2 force-pushed the fix/localtime-thread-safety-and-leap-year branch from 4af095c to c391f85 Compare March 3, 2026 19:20
@rouault
Copy link
Member

rouault commented Mar 3, 2026

@kbevers I see the original formula to translate to decimal year comes from 0b5c362 . I remember that ISO 19111 doesn't mention anything about that (or maybe that leap years don't matter). Anyway in src/conversions/unitconvert.cpp, we do take into leap years. Should we align hgridshift and vgridship on that ?

Comment on lines 165 to 166
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the refactoring can be done now

@kbevers
Copy link
Member

kbevers commented Mar 3, 2026

@kbevers I see the original formula to translate to decimal year comes from 0b5c362 . I remember that ISO 19111 doesn't mention anything about that (or maybe that leap years don't matter). Anyway in src/conversions/unitconvert.cpp, we do take into leap years. Should we align hgridshift and vgridship on that ?

It's been a while so I don't remember my thought process but I guess I didn't see any reason to complicate things. Usually we are looking a rates of mm or cm pr year in a deformation model. The difference between 1/365 and 1/366 of a year is neglicable and well within the uncertainty of any imperical model. But accounting for leap years is more correct and with a bit of refactoring everything will be a little bit nicer for the next person.

@KinshukSS2
Copy link
Contributor Author

I have refactored the duplicated t_final code from hgridshift.cpp and vgridshift.cpp into a shared function pj_parse_t_final()
did some thorough testing of builds as well as functionalities to make sure it works as intended
pls do give a look into it and happy to make changes if it suits the intended plan of making a reusable func
note: i am seeing a failure in the file_api test ,hoping it is not related to the refactoring

@KinshukSS2 KinshukSS2 force-pushed the fix/localtime-thread-safety-and-leap-year branch from 34e6486 to 903cbdb Compare March 4, 2026 12:32
rouault
rouault approved these changes Mar 4, 2026
@KinshukSS2 KinshukSS2 changed the title fix: replace non-thread-safe localtime() with localtime_r/localtime_s… Refactor time parsing with thread-safe localtime and leap year fix Mar 4, 2026
@kbevers
Copy link
Member

kbevers commented Mar 5, 2026

The refactored time function looks good. I'd like to see a more descriptive commit message for the clang-format fix, as it's not clear to me what is actually being fixed.

@KinshukSS2
Copy link
Contributor Author

@kbevers

i think it would be better if i will squash all the 3 commits into one in order to not create any chaos and give a proper description

@KinshukSS2 KinshukSS2 force-pushed the fix/localtime-thread-safety-and-leap-year branch from 903cbdb to 1408e44 Compare March 5, 2026 07:41
@kbevers
Copy link
Member

kbevers commented Mar 5, 2026

i think it would be better if i will squash all the 3 commits into one in order to not create any chaos and give a proper description

That's an option, yes. It still doesn't explain what's going on with the changes to satisfy clang-format. If I look at this commit in ten years I'd like to know why changes regarding opening of grid files is mixed with refactoring of functionality to parse time. Ideally this PR is rebased into two commits: one with the changes to time parsing and the other that fixes whatever clang-format complains about.

@KinshukSS2
Copy link
Contributor Author

@kbevers so you would recommend me splitting it into two commits one stating about the clang fixtures (due to CI failures i faced) and the other one abt refactoring ?
wanted to confirm before i proceed

@kbevers
Copy link
Member

kbevers commented Mar 5, 2026

Yes

Extract duplicated t_final parameter parsing logic from hgridshift.cpp
and vgridshift.cpp into pj_parse_t_final() function in param.cpp.

Changes:
- Add pj_parse_t_final() to param.cpp with thread-safe time handling
- Replace localtime() with localtime_r()/localtime_s() for thread safety
- Fix leap year calculation (proper 365/366 day handling)
- Support both numeric t_final values and t_final=now keyword
- Remove duplicate code from transformation files
- Add function declaration to proj_internal.h

Resolves TODO comment present in both transformation files.
Fixes thread safety issue when multiple threads use +t_final=now.
@KinshukSS2 KinshukSS2 force-pushed the fix/localtime-thread-safety-and-leap-year branch from 1408e44 to 645954b Compare March 5, 2026 14:08
@KinshukSS2
Copy link
Contributor Author

@kbevers the clang format issue from the ci failure was specifically abt formating the new code (one i added)

it would be counterproductive to create one commit with improperly formatted new code and then a second commit just to fix that formatting

the refactoring should contain the properly formatted code from the start istelf
hoping i've understood the way you interpreted the situation

@kbevers
Copy link
Member

kbevers commented Mar 5, 2026

@KinshukSS2 in a previous rendition of this PR you had changes in src/transformations/gridshift.cpp (seen in this commit 1408e44), those are what I was asking for more information on. They aren't present in the latest (and only) commit, so no need to dwelve into that.

@jjimenezshaw
Copy link
Contributor

@KinshukSS2 in a previous rendition of this PR you had changes in src/transformations/gridshift.cpp (seen in this commit 1408e44), those are what I was asking for more information on. They aren't present in the latest (and only) commit, so no need to dwelve into that.

Those changes are about using std::lock_guard<std::mutex> instead of lock and unlock. It is not about clang-format.

@kbevers
Copy link
Member

kbevers commented Mar 5, 2026

Those changes are about using std::lock_guardstd::mutex instead of lock and unlock. It is not about clang-format.

Well, they were initially put in a commit that said "fix clang-format" which has since been force-pushed away. And now the changes aren't here at all. The thing I've been going on about was to get an explanation for what was going on, as it didn't look like anything to do with the stated purpose of the PR. But that discussion is futile now that those lines of code are gone from the PR.

This is ready to merge once the tests have run successfully.

@rouault rouault closed this Mar 5, 2026
@rouault rouault reopened this Mar 5, 2026
@rouault rouault added this to the 9.9.0 milestone Mar 5, 2026
@rouault rouault merged commit ee3a0bd into OSGeo:master Mar 5, 2026
49 of 59 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-thread-safe localtime() + incorrect leap year calculation

4 participants