Skip to content

Commit 2ee9632

Browse files
author
ci bot
committed
Merge branch 'fix/windows-excel-export-error' into 'enterprise'
fix: use cross-platform date formatting for Excel export and schedule display See merge request dkinternal/testgen/dataops-testgen!550
2 parents 2a349c4 + 0bd1764 commit 2ee9632

6 files changed

Lines changed: 18 additions & 6 deletions

File tree

testgen/common/cron_service.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import cron_converter
66
import cron_descriptor
77

8+
from testgen.common import date_service
9+
810

911
class CronSample(TypedDict, total=False):
1012
id: str | None
@@ -26,7 +28,7 @@ def get_cron_sample(
2628
cron_schedule = cron_obj.schedule(reference_time or datetime.now(zoneinfo.ZoneInfo(cron_tz)))
2729
readable_cron_schedule = cron_descriptor.get_description(cron_expr)
2830
if formatted:
29-
samples = [cron_schedule.next().strftime("%a %b %-d, %-I:%M %p") for _ in range(sample_count)]
31+
samples = [date_service.format_friendly_datetime(cron_schedule.next(), "%a %b %-d, %-I:%M %p") for _ in range(sample_count)]
3032
else:
3133
samples = [int(cron_schedule.next().timestamp()) for _ in range(sample_count)]
3234
except zoneinfo.ZoneInfoNotFoundError:

testgen/common/date_service.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,19 @@ def accommodate_dataframe_to_timezone(df, streamlit_session, time_columns=None):
9797
df[time_column] = df[time_column].dt.strftime("%Y-%m-%d %H:%M:%S")
9898

9999

100+
def format_friendly_datetime(dt: datetime, fmt: str) -> str:
101+
"""Cross-platform strftime: replaces Linux-only %-d and %-I before calling strftime."""
102+
return dt.strftime(fmt.replace("%-d", str(dt.day)).replace("%-I", str(dt.hour % 12 or 12)))
103+
104+
100105
def get_timezoned_timestamp(streamlit_session, value, dateformat="%b %-d, %-I:%M %p"):
101106
ret = None
102107
if value and "browser_timezone" in streamlit_session:
103108
data = {"value": [value]}
104109
df = pd.DataFrame(data)
105110
timezone = streamlit_session["browser_timezone"]
106-
df["value"] = df["value"].dt.tz_localize("UTC").dt.tz_convert(timezone).dt.strftime(dateformat)
111+
df["value"] = df["value"].dt.tz_localize("UTC").dt.tz_convert(timezone).apply(
112+
lambda dt: format_friendly_datetime(dt, dateformat) if pd.notna(dt) else ""
113+
)
107114
ret = df.iloc[0, 0]
108115
return ret

testgen/common/notifications/notifications.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import math
22
from datetime import datetime
33

4+
from testgen.common import date_service
45
from testgen.common.notifications.base import BaseEmailTemplate
56
from testgen.utils import friendly_score
67

@@ -14,7 +15,7 @@ def format_number_helper(self, number: int) -> str:
1415
return "" if number is None else f"{number:,}"
1516

1617
def format_dt_helper(self, dt: datetime) -> str:
17-
return "" if dt is None else dt.strftime("%b %d, %-I:%M %p UTC")
18+
return "" if dt is None else date_service.format_friendly_datetime(dt, "%b %d, %-I:%M %p UTC")
1819

1920
def format_duration_helper(self, start_time: datetime, end_time: datetime) -> str:
2021
total_seconds = abs(end_time - start_time).total_seconds()

testgen/ui/views/data_catalog.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from sqlalchemy.sql.expression import func as sa_func
1212
from streamlit.delta_generator import DeltaGenerator
1313

14+
from testgen.common import date_service
1415
from testgen.common.data_catalog_service import (
1516
apply_column_metadata,
1617
apply_table_metadata,
@@ -492,7 +493,7 @@ def get_excel_report_data(update_progress: PROGRESS_UPDATE_TYPE, table_group: Ta
492493

493494
for key in ["min_date", "max_date", "add_date", "last_mod_date", "drop_date"]:
494495
data[key] = data[key].apply(
495-
lambda val: val.strftime("%b %-d %Y, %-I:%M %p") if not pd.isna(val) and not isinstance(val, str) else val
496+
lambda val: date_service.format_friendly_datetime(val, "%b %-d %Y, %-I:%M %p") if not pd.isna(val) and not isinstance(val, str) else val
496497
)
497498

498499
for key in ["data_source", "source_system", "source_process", "business_domain", "stakeholder_group", "transform_level", "aggregation_level", "data_product"]:

testgen/ui/views/dialogs/manage_schedules.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from sqlalchemy import select
77
from sqlalchemy.exc import IntegrityError
88

9+
from testgen.common import date_service
910
from testgen.common.models import Session, with_database_session
1011
from testgen.common.models.scheduler import JobSchedule
1112
from testgen.ui.session import session
@@ -55,7 +56,7 @@ def build_data(self) -> dict:
5556
"readableExpr": cron_descriptor.get_description(job.cron_expr),
5657
"cronTz": job.cron_tz_str,
5758
"sample": [
58-
sample.strftime("%a %b %-d, %-I:%M %p")
59+
date_service.format_friendly_datetime(sample, "%a %b %-d, %-I:%M %p")
5960
for sample in job.get_sample_triggering_timestamps(CRON_SAMPLE_COUNT + 1)
6061
],
6162
"active": job.active,

testgen/ui/views/test_definitions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ def get_excel_report_data(
768768

769769
for key in ["profiling_as_of_date", "last_manual_update"]:
770770
data[key] = data[key].apply(
771-
lambda val: datetime.strptime(val, "%Y-%m-%d %H:%M:%S").strftime("%b %-d %Y, %-I:%M %p")
771+
lambda val: date_service.format_friendly_datetime(datetime.strptime(val, "%Y-%m-%d %H:%M:%S"), "%b %-d %Y, %-I:%M %p")
772772
if (val and not pd.isna(val) and val != "NaT")
773773
else None
774774
)

0 commit comments

Comments
 (0)