1212 pymysql = None
1313
1414
15+ # Python 3.7 added ``datetime.fromisoformat``. Provide a minimal fallback so the
16+ # code continues to work on older interpreters where it is unavailable.
17+ try : # pragma: no cover - behaviour depends on Python version
18+ _fromisoformat = datetime .fromisoformat
19+ except AttributeError : # pragma: no cover - executed on Python < 3.7
20+ def _fromisoformat (value ):
21+ for fmt in ("%Y-%m-%dT%H:%M:%S" , "%Y-%m-%d %H:%M:%S" , "%Y-%m-%d" ):
22+ try :
23+ return datetime .strptime (value , fmt )
24+ except ValueError :
25+ continue
26+ raise ValueError (f"Invalid isoformat string: { value !r} " )
27+
1528STATE_FILE = os .path .expanduser ("last_run.json" )
1629
1730JOB_STATE_MAP = {
@@ -138,7 +151,7 @@ def _validate_time(self, value, name):
138151 # Convert YYYY-MM-DD strings to a UNIX timestamp so comparisons
139152 # against numeric time_start/time_end columns work correctly.
140153 try :
141- dt = datetime . fromisoformat (value )
154+ dt = _fromisoformat (value )
142155 return int (dt .timestamp ())
143156 except ValueError :
144157 pass
@@ -151,7 +164,7 @@ def _to_datetime(self, value):
151164 if isinstance (value , (int , float )):
152165 return datetime .fromtimestamp (value )
153166 if isinstance (value , str ):
154- return datetime . fromisoformat (value )
167+ return _fromisoformat (value )
155168 raise TypeError ("Unsupported time format" )
156169
157170 def _load_cluster_name (self , conf_path ):
@@ -548,12 +561,12 @@ def export_summary(self, start_time, end_time):
548561 total_gpu += vals .get ('gpu_hours' , 0.0 )
549562 total_cost += acct_cost
550563 start_dt = (
551- datetime . fromisoformat (start_time )
564+ _fromisoformat (start_time )
552565 if isinstance (start_time , str )
553566 else datetime .fromtimestamp (start_time )
554567 )
555568 end_dt = (
556- datetime . fromisoformat (end_time )
569+ _fromisoformat (end_time )
557570 if isinstance (end_time , str )
558571 else datetime .fromtimestamp (end_time )
559572 )
@@ -637,7 +650,7 @@ def _export_day(day):
637650 if args .auto_daily and not args .start and not args .end :
638651 last = _read_last_run ()
639652 if last :
640- start = datetime . fromisoformat (last ).date () + timedelta (days = 1 )
653+ start = _fromisoformat (last ).date () + timedelta (days = 1 )
641654 else :
642655 start = date .today () - timedelta (days = 1 )
643656 end = date .today () if start < date .today () else start
0 commit comments