session-slides 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/html_generator.py +33 -40
package/package.json
CHANGED
|
@@ -1056,6 +1056,8 @@ def _format_datetime(dt_string: str) -> tuple:
|
|
|
1056
1056
|
"""
|
|
1057
1057
|
Parse and format a datetime string into readable date and time components.
|
|
1058
1058
|
|
|
1059
|
+
Converts UTC timestamps to the local timezone before formatting.
|
|
1060
|
+
|
|
1059
1061
|
Args:
|
|
1060
1062
|
dt_string: ISO format datetime string or similar
|
|
1061
1063
|
|
|
@@ -1065,32 +1067,33 @@ def _format_datetime(dt_string: str) -> tuple:
|
|
|
1065
1067
|
if not dt_string:
|
|
1066
1068
|
return None, None
|
|
1067
1069
|
|
|
1068
|
-
#
|
|
1069
|
-
clean_dt = re.sub(r'[+-]\d{2}:\d{2}$', '', dt_string)
|
|
1070
|
-
|
|
1071
|
-
# Try various datetime formats
|
|
1072
|
-
formats = [
|
|
1073
|
-
'%Y-%m-%dT%H:%M:%S.%fZ',
|
|
1074
|
-
'%Y-%m-%dT%H:%M:%SZ',
|
|
1075
|
-
'%Y-%m-%dT%H:%M:%S.%f',
|
|
1076
|
-
'%Y-%m-%dT%H:%M:%S',
|
|
1077
|
-
'%Y-%m-%d %H:%M:%S.%f',
|
|
1078
|
-
'%Y-%m-%d %H:%M:%S',
|
|
1079
|
-
'%Y-%m-%d',
|
|
1080
|
-
]
|
|
1081
|
-
|
|
1070
|
+
# Try Python's fromisoformat first (handles +00:00, Z, microseconds)
|
|
1082
1071
|
dt = None
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1072
|
+
try:
|
|
1073
|
+
dt = datetime.fromisoformat(dt_string.replace('Z', '+00:00'))
|
|
1074
|
+
except (ValueError, AttributeError):
|
|
1075
|
+
# Fall back to manual parsing for non-standard formats
|
|
1076
|
+
clean_dt = re.sub(r'[+-]\d{2}:\d{2}$', '', dt_string)
|
|
1077
|
+
for fmt in [
|
|
1078
|
+
'%Y-%m-%dT%H:%M:%S.%f',
|
|
1079
|
+
'%Y-%m-%dT%H:%M:%S',
|
|
1080
|
+
'%Y-%m-%d %H:%M:%S.%f',
|
|
1081
|
+
'%Y-%m-%d %H:%M:%S',
|
|
1082
|
+
'%Y-%m-%d',
|
|
1083
|
+
]:
|
|
1084
|
+
try:
|
|
1085
|
+
dt = datetime.strptime(clean_dt, fmt)
|
|
1086
|
+
break
|
|
1087
|
+
except ValueError:
|
|
1088
|
+
continue
|
|
1089
1089
|
|
|
1090
1090
|
if dt is None:
|
|
1091
|
-
# Return the raw string if we can't parse it
|
|
1092
1091
|
return dt_string, None
|
|
1093
1092
|
|
|
1093
|
+
# Convert to local timezone if the datetime is timezone-aware
|
|
1094
|
+
if dt.tzinfo is not None:
|
|
1095
|
+
dt = dt.astimezone()
|
|
1096
|
+
|
|
1094
1097
|
# Format nicely: "February 4, 2026" and "2:30 PM"
|
|
1095
1098
|
date_str = dt.strftime('%B %d, %Y').replace(' 0', ' ') # Remove leading zero from day
|
|
1096
1099
|
time_str = dt.strftime('%I:%M %p').lstrip('0') # Remove leading zero from hour
|
|
@@ -1120,28 +1123,18 @@ def _calculate_duration(turns: list) -> str:
|
|
|
1120
1123
|
if len(timestamps) < 2:
|
|
1121
1124
|
return None
|
|
1122
1125
|
|
|
1123
|
-
#
|
|
1124
|
-
first_ts = re.sub(r'[+-]\d{2}:\d{2}$', '', timestamps[0])
|
|
1125
|
-
last_ts = re.sub(r'[+-]\d{2}:\d{2}$', '', timestamps[-1])
|
|
1126
|
-
|
|
1127
|
-
# Try to parse first and last timestamps
|
|
1128
|
-
formats = [
|
|
1129
|
-
'%Y-%m-%dT%H:%M:%S.%fZ',
|
|
1130
|
-
'%Y-%m-%dT%H:%M:%SZ',
|
|
1131
|
-
'%Y-%m-%dT%H:%M:%S.%f',
|
|
1132
|
-
'%Y-%m-%dT%H:%M:%S',
|
|
1133
|
-
]
|
|
1134
|
-
|
|
1126
|
+
# Parse first and last timestamps
|
|
1135
1127
|
first_dt = None
|
|
1136
1128
|
last_dt = None
|
|
1137
|
-
|
|
1138
|
-
for fmt in formats:
|
|
1129
|
+
for ts_str, target in [(timestamps[0], 'first'), (timestamps[-1], 'last')]:
|
|
1139
1130
|
try:
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1131
|
+
dt = datetime.fromisoformat(ts_str.replace('Z', '+00:00'))
|
|
1132
|
+
except (ValueError, AttributeError):
|
|
1133
|
+
dt = None
|
|
1134
|
+
if target == 'first':
|
|
1135
|
+
first_dt = dt
|
|
1136
|
+
else:
|
|
1137
|
+
last_dt = dt
|
|
1145
1138
|
|
|
1146
1139
|
if first_dt is None or last_dt is None:
|
|
1147
1140
|
return None
|