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

Adding UTC APIs #6909

Merged
merged 13 commits into from
Jan 28, 2021
Merged

Conversation

ThePotatoGuy
Copy link
Member

@ThePotatoGuy ThePotatoGuy commented Jan 20, 2021

Partial #2312

New coding conventions with this PR

  • All code going forward should save times in UTC. (Exceptions are any data structures that contain non-UTC time, like Event databases and docking station log times)
  • All code going forward should use datetime.utcnow() instead of datetime.now()
  • Do NOT save a datetime with tzinfo populated. If you are doing utc_to_local, and want to save the result to persistent, you need to clear the tzinfo with a dt.replace(tzinfo=None). local_to_utc will always return a datetime without tzinfo set.
  • All datetime math should be done in UTC. Only convert to local when you need to show the user or the datetime needs to be localized because of existing data structure exceptions.

Key Changes

  • new APIs for converting datetimes between UTC and local:
    • mas_utils.local_to_utc - converts a naive local datetime into UTC - NOTE: this exists mainly for dealing with our current set of non-UTC times. As we transition to UTC, we should almost never have to use this.
      • this will reload the local timezone by default
    • mas_utils.utc_to_any - converts a naive utc datetime into a datetime for any timezone, using pytz.tzinfo object. This sets tzinfo
    • mas_utils.utc_to_local - converts a naive utc datetime into a localtime. This sets tzinfo
      • this will reload the local timezone by default
    • mas_utils.get_localzone - gets the local timezone object
    • mas_utils.reload_localzone - reloads the local timezone object and returns it. this should be used if the current timezone may have changed.
  • added pytz and tzlocal libraries for time management. pytz has implementations of tzinfo objects which are required to use datetimes with timezones. tzlocal has a function for retrieving the local timezone as a pytz.tzinfo object.
    • NOTE: I have edited the pytz library so it can support loading timezone info locally.
  • MASLocalTz - special extension of pytz.tzinfo.StaticTzInfo that is compatible with pytz and datetime.tzinfo. This builds a timezone naively using the time.timezone/altzone/daylight libraries. (See pytz considerations section as to why this is needed).
  • added unit tests for the UTC APIs
  • fixed a crash in the unit test menu

pytz considerations

The actual pytz library contains a bunch of special files that are used to build timezones. Since time is complicated, there are many of these files, and including them would double the filecount of the mod. The only real benefit to having these timezones is to do time math that span timezones. For example, if we had a direct scheduling system in the mod (like planning dates at specific times), then we would need the timezone information to accurately handle things like DST.

Since we don't need this information to do accurate utc -> local time, I decided not to include them. If we do need these in the future, however, we should look at all the options for adding the files, like only including them as a zip and then extracting them when installed. (or once we have a full installer, we could simply request the pytz package to be installed for the system).

So in order to handle timezones without having actual timezone information, I've created MASLocalTz, which can build a pytz.tzinfo object that works as a local timezone just as well as a real timezone for standard utc-local conversions. What it cannot do is determine if a specific date and time should be in DST or not for the local timezone. All it can do is adjust itself automatically when the local timezone changes (either to/from DST or to any specific timezone, like when the user changes it).

timezone load order

When MAS loads, pytz will attempt to load timezone info from file. This happens as follows:

  1. Environment var PYTZ_TZDATADIR is checked. This would likely be set if a user installs pytz to their system. If this env var is found, timezone data will be loaded from this directory.
  2. Otherwise, python-packages/pytz/zoneinfo/ will be checked. This would be how we would load timezones if we shipped them with the mod
  3. Otherwise, MASLocalTz is always used, and we will not have standard timezone information.

Testing

  • run the UTC APIs unit test (Hey ... > Dev > TEST UNITTESTS > UTC APIs)
  • If you have pytz installed and the env var set, you can try mas_utils.get_localzone() in console. You should get a real timezone in this case. (You may need to add the env var to environment.txt if renpy doesn't find it. I've had mixed results).
  • can also try unpacking the zip below so it is in a zoneinfo folder in the pytz python-package. Should get a real timezone as well.

zoneinfo.zip

@ThePotatoGuy ThePotatoGuy added this to the Next Release milestone Jan 21, 2021
@ThePotatoGuy ThePotatoGuy added awaiting code review someone needs to check for syntax/logic/indentation errors awaiting testing code needs to be tested labels Jan 21, 2021
@ThePotatoGuy ThePotatoGuy marked this pull request as ready for review January 21, 2021 04:56
@ThePotatoGuy ThePotatoGuy merged commit e02864e into Monika-After-Story:content Jan 28, 2021
@ThePotatoGuy ThePotatoGuy removed awaiting code review someone needs to check for syntax/logic/indentation errors awaiting testing code needs to be tested labels Jan 28, 2021
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.

4 participants