33from six import string_types
44import json
55import decimal
6- import os
7-
6+ import datetime
87
98from plotly .io ._utils import validate_coerce_fig_to_dict , validate_coerce_output_type
109from _plotly_utils .optional_imports import get_module
@@ -474,12 +473,19 @@ def clean_to_json_compatible(obj, **kwargs):
474473 if np is not None :
475474 if obj is np .ma .core .masked :
476475 return float ("nan" )
477- elif (
478- numpy_allowed
479- and isinstance (obj , np .ndarray )
480- and obj .dtype .kind in ("b" , "i" , "u" , "f" )
481- ):
482- return np .ascontiguousarray (obj )
476+ elif isinstance (obj , np .ndarray ):
477+ if numpy_allowed and obj .dtype .kind in ("b" , "i" , "u" , "f" ):
478+ return np .ascontiguousarray (obj )
479+ elif obj .dtype .kind == "M" :
480+ # datetime64 array
481+ return np .datetime_as_string (obj ).tolist ()
482+ elif obj .dtype .kind == "U" :
483+ return obj .tolist ()
484+ elif obj .dtype .kind == "O" :
485+ # Treat object array as a lists, continue processing
486+ obj = obj .tolist ()
487+ elif isinstance (obj , np .datetime64 ):
488+ return str (obj )
483489
484490 # pandas
485491 if pd is not None :
@@ -496,35 +502,29 @@ def clean_to_json_compatible(obj, **kwargs):
496502
497503 if not datetime_allowed :
498504 # Note: We don't need to handle dropping timezones here because
499- # numpy's datetime64 doesn't support them and pandas's tolist()
500- # doesn't preserve them.
505+ # numpy's datetime64 doesn't support them and pandas's tz_localize
506+ # above drops them.
501507 for i in range (len (dt_values )):
502508 dt_values [i ] = dt_values [i ].isoformat ()
503509
504510 return dt_values
505511
506512 # datetime and date
507- if not datetime_allowed :
508- try :
509- # Need to drop timezone for scalar datetimes
510- return obj .replace (tzinfo = None ).isoformat ()
511- except (TypeError , AttributeError ):
512- pass
513+ try :
514+ # Need to drop timezone for scalar datetimes. Don't need to convert
515+ # to string since engine can do that
516+ obj = obj .replace (tzinfo = None )
517+ obj = obj .to_pydatetime ()
518+ except (TypeError , AttributeError ):
519+ pass
513520
514- if np and isinstance (obj , np .datetime64 ):
515- return str (obj )
516- else :
517- res = None
521+ if not datetime_allowed :
518522 try :
519- # Need to drop timezone for scalar datetimes. Don't need to convert
520- # to string since engine can do that
521- res = obj .replace (tzinfo = None )
522- res = res .to_pydatetime ()
523+ return obj .isoformat ()
523524 except (TypeError , AttributeError ):
524525 pass
525-
526- if res is not None :
527- return res
526+ elif isinstance (obj , datetime .datetime ):
527+ return obj
528528
529529 # Try .tolist() convertible, do not recurse inside
530530 try :
0 commit comments