Spaces:
Running
Running
rmm
commited on
Commit
·
0cc6a8a
1
Parent(s):
cf8541f
fix: timezone from file metadata, or from locale if absent
Browse files- src/input/input_handling.py +24 -5
- src/input/input_validator.py +22 -0
src/input/input_handling.py
CHANGED
@@ -11,7 +11,7 @@ import cv2
|
|
11 |
import numpy as np
|
12 |
|
13 |
from input.input_observation import InputObservation
|
14 |
-
from input.input_validator import get_image_datetime, is_valid_email, is_valid_number, get_image_latlon
|
15 |
|
16 |
m_logger = logging.getLogger(__name__)
|
17 |
m_logger.setLevel(logging.INFO)
|
@@ -186,6 +186,7 @@ def metadata_inputs_one_file(file:UploadedFile, image_hash:str, dbg_ix:int=0) ->
|
|
186 |
author_email = st.session_state["input_author_email"]
|
187 |
filename = file.name
|
188 |
image_datetime_raw = get_image_datetime(file)
|
|
|
189 |
latitude0, longitude0 = get_image_latlon(file)
|
190 |
msg = f"[D] {filename}: lat, lon from image metadata: {latitude0}, {longitude0}"
|
191 |
m_logger.debug(msg)
|
@@ -226,11 +227,29 @@ def metadata_inputs_one_file(file:UploadedFile, image_hash:str, dbg_ix:int=0) ->
|
|
226 |
# 5. Date/time
|
227 |
## first from image metadata
|
228 |
if image_datetime_raw is not None:
|
229 |
-
|
230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
else:
|
232 |
-
|
233 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
|
235 |
## either way, give user the option to enter manually (or correct, e.g. if camera has no rtc clock)
|
236 |
date = viewcontainer.date_input("Date for "+filename, value=date_value, key=f"input_date_{image_hash}")
|
|
|
11 |
import numpy as np
|
12 |
|
13 |
from input.input_observation import InputObservation
|
14 |
+
from input.input_validator import get_image_datetime, is_valid_email, is_valid_number, get_image_latlon, get_image_timezone
|
15 |
|
16 |
m_logger = logging.getLogger(__name__)
|
17 |
m_logger.setLevel(logging.INFO)
|
|
|
186 |
author_email = st.session_state["input_author_email"]
|
187 |
filename = file.name
|
188 |
image_datetime_raw = get_image_datetime(file)
|
189 |
+
image_timezone_raw = get_image_timezone(file)
|
190 |
latitude0, longitude0 = get_image_latlon(file)
|
191 |
msg = f"[D] {filename}: lat, lon from image metadata: {latitude0}, {longitude0}"
|
192 |
m_logger.debug(msg)
|
|
|
227 |
# 5. Date/time
|
228 |
## first from image metadata
|
229 |
if image_datetime_raw is not None:
|
230 |
+
# if we have a timezone let's use it (but only if we also have datetime)
|
231 |
+
time_fmt = '%Y:%m:%d %H:%M:%S'
|
232 |
+
if image_timezone_raw is not None:
|
233 |
+
image_datetime_raw += f" {image_timezone_raw}"
|
234 |
+
time_fmt += ' %z'
|
235 |
+
#
|
236 |
+
dt = datetime.datetime.strptime(image_datetime_raw, time_fmt)
|
237 |
+
date_value = dt.date()
|
238 |
+
time_value = dt.time()
|
239 |
+
tz_value = dt.tzinfo # could be None...
|
240 |
+
|
241 |
+
#time_value = datetime.datetime.strptime(image_datetime_raw, '%Y:%m:%d %H:%M:%S').time()
|
242 |
+
#date_value = datetime.datetime.strptime(image_datetime_raw, '%Y:%m:%d %H:%M:%S').date()
|
243 |
else:
|
244 |
+
# get current time, with user timezone (or is it server timezone?! TODO: test with different zones)
|
245 |
+
dt = datetime.datetime.now().astimezone().replace(microsecond=0)
|
246 |
+
time_value = dt.time()
|
247 |
+
date_value = dt.date()
|
248 |
+
tz_value = dt.tzinfo
|
249 |
+
|
250 |
+
#time_value = datetime.datetime.now().time() # Default to current time
|
251 |
+
#date_value = datetime.datetime.now().date()
|
252 |
+
|
253 |
|
254 |
## either way, give user the option to enter manually (or correct, e.g. if camera has no rtc clock)
|
255 |
date = viewcontainer.date_input("Date for "+filename, value=date_value, key=f"input_date_{image_hash}")
|
src/input/input_validator.py
CHANGED
@@ -84,6 +84,28 @@ def get_image_datetime(image_file:UploadedFile) -> Union[str, None]:
|
|
84 |
# TODO: add to logger
|
85 |
return None
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
def decimal_coords(coords:tuple, ref:str) -> Fraction:
|
89 |
"""
|
|
|
84 |
# TODO: add to logger
|
85 |
return None
|
86 |
|
87 |
+
# function to extract the timezone from image metadata
|
88 |
+
def get_image_timezone(image_file:UploadedFile) -> Union[str, None]:
|
89 |
+
"""
|
90 |
+
Extracts the timezone from the EXIF metadata of an uploaded image file.
|
91 |
+
|
92 |
+
Args:
|
93 |
+
image_file (UploadedFile): The uploaded image file from which to extract the timezone.
|
94 |
+
|
95 |
+
Returns:
|
96 |
+
str: The timezone as a string if available, otherwise None.
|
97 |
+
|
98 |
+
Raises:
|
99 |
+
Warning: If the timezone could not be extracted from the image metadata.
|
100 |
+
"""
|
101 |
+
try:
|
102 |
+
image = Image.open(image_file)
|
103 |
+
exif_data = image._getexif()
|
104 |
+
if exif_data is not None:
|
105 |
+
if ExifTags.Base.OffsetTimeOriginal in exif_data:
|
106 |
+
return exif_data.get(ExifTags.Base.OffsetTimeOriginal)
|
107 |
+
except Exception as e: # FIXME: what types of exception?
|
108 |
+
st.warning(f"Could not extract timezone from image metadata. (file: {image_file.name})")
|
109 |
|
110 |
def decimal_coords(coords:tuple, ref:str) -> Fraction:
|
111 |
"""
|