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

Look at using tzfpy to restore timezone name when importing #1788

Open
RhetTbull opened this issue Jan 25, 2025 · 8 comments
Open

Look at using tzfpy to restore timezone name when importing #1788

RhetTbull opened this issue Jan 25, 2025 · 8 comments
Labels
feature request New feature or request

Comments

@RhetTbull
Copy link
Owner

Currently, the timezone name for a photo cannot be preserved on export. Both the XMP sidecar format and the --exiftool option preserve the UTC offset but this does not preserve the named timezone (e.g. America/Los_Angeles). When restoring a photo with osxphotos import, osxphotos will select a timezone that matches the UTC offset for the photo but this does not guarantee that it is the correct timezone name. The metadata standards do not allow the specification of the name, only the UTC offset. Using something like tzfpy would allow osxphotos to guess the most likely timezone based on the location and date/time of the photo.

@oPromessa
Copy link
Contributor

I'm using timezonefinder:

  • To identify in Photos all pics with mismatched GPS Location vs Timezone.
  • I also compare with the pics's file EXIF data for incongruences (much like timewarp --inspect and --compare)
  • I manually add locations to pics without GPS info. Can't really use add-locations as it may fail when I have pics with wrong timezone side-by-side with others.
  • I then generate push-exif and timewarp commands to fix things.

First load takes time, reason why I asked about the option to reuse a loaded module on this discussion. Following that it runs fine. Did not fully test to compare speeds with tzfpy -- will try it.

They compare it with tzfpy here

@RhetTbull
Copy link
Owner Author

Thanks. I looked at timezonefinder but as you said it has slow load times and the package is rather bloated and that would increase the size of the osxphotos stand-alone executable (and slow load time for osxphotos even more). For the relatively narrow use case of fixing timezones upon import, it looks to me like tzfpy is sufficient. It loads and runs very fast. It's still a bit bloated at 12.7MB for macOS package but that's better than 51.3MB for timezonefinder.

@RhetTbull
Copy link
Owner Author

To identify in Photos all pics with mismatched GPS Location vs Timezone.
I also compare with the pics's file EXIF data for incongruences (much like timewarp --inspect and --compare)

That might be a useful tool to build into osxphotos.

@RhetTbull
Copy link
Owner Author

Rather than using an external package, I think this can be done entirely using macOS native APIs. The following takes about 300ms per call on my Intel MacBook Air and about 200ms on my M1 Mac Mini. This is comparable to what I saw from tzfpy without the added dependency.

python tz.py
Timezone: America/Los_Angeles, offset: -28800, took: 223.70 ms
"""Get named timezone for a location"""

import time

import objc
from CoreLocation import CLGeocoder, CLLocation
from Foundation import NSDate, NSRunLoop, NSTimeZone

SLEEP = 0.01

def timezone_for_location(latitude: float, longitude: float) -> NSTimeZone:
    location = CLLocation.alloc().initWithLatitude_longitude_(latitude, longitude)
    geocoder = CLGeocoder.alloc().init()

    result = {"timezone": None, "error": None}
    completed = False

    def completion(placemarks, error):
        nonlocal completed
        if error:
            result["error"] = error.localizedDescription()
        else:
            placemark = placemarks[0] if placemarks else None
            if placemark and placemark.timeZone():
                result["timezone"] = placemark.timeZone()
            else:
                result["error"] = "Unable to determine timezone"
        completed = True

    geocoder.reverseGeocodeLocation_completionHandler_(location, completion)

    while not completed:
        NSRunLoop.currentRunLoop().runMode_beforeDate_(
            "NSDefaultRunLoopMode", NSDate.dateWithTimeIntervalSinceNow_(SLEEP)
        )
        time.sleep(SLEEP)

    if result["error"]:
        raise Exception(f"Error: {result['error']}")

    return result["timezone"]


if __name__ == "__main__":
    latitude, longitude = 34, -118  # Los Angeles
    date = NSDate.date()

    try:
        start_t = time.time_ns()
        timezone = timezone_for_location(latitude, longitude)
        offset = timezone.secondsFromGMTForDate_(date)
        end_t = time.time_ns()
        print(
            f"Timezone: {timezone.name()}, offset: {offset}, took: {(end_t - start_t) / 1e6:.2f} ms"
        )
    except Exception as e:
        print(e)

@RhetTbull
Copy link
Owner Author

I've created a gist with a more robust version with error checking and timeout.

@oPromessa
Copy link
Contributor

oPromessa commented Jan 26, 2025

To identify in Photos all pics with mismatched GPS Location vs Timezone.
I also compare with the pics's file EXIF data for incongruences (much like timewarp --inspect and --compare)

That might be a useful tool to build into osxphotos.

Definitely. Must still cleanup a bit the code.

Looking forward to the DST adjustment in #1777

@oPromessa
Copy link
Contributor

I've created a gist with a more robust version with error checking and timeout.

Changed my code to, based on your gist, use Apple Foundation to get TimeZone based on geolocation.
After a few tests and while batch processing ~477 pics, I bumped into error kCLErrorDomain error 2.after ~80 pics processed.

Found this 11-year old reference kCLErrorDomain error 2 after geocoding repeatedly with CLGeocoder to the fact that the docs say "you should not send more than one geocoding request per minute".

Just wanted to let you know, should you go this route.

For now I'm going to continue to use timezonefinder or maybe use tzfpy once you incorporate it in osxphotos.

@RhetTbull
Copy link
Owner Author

Well that stinks. Thanks for pointing this out. I'll take a look at tzfpy again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants