3
3
from six import string_types
4
4
import json
5
5
import decimal
6
- import os
7
-
6
+ import datetime
8
7
9
8
from plotly .io ._utils import validate_coerce_fig_to_dict , validate_coerce_output_type
10
9
from _plotly_utils .optional_imports import get_module
@@ -474,12 +473,19 @@ def clean_to_json_compatible(obj, **kwargs):
474
473
if np is not None :
475
474
if obj is np .ma .core .masked :
476
475
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 )
483
489
484
490
# pandas
485
491
if pd is not None :
@@ -496,35 +502,29 @@ def clean_to_json_compatible(obj, **kwargs):
496
502
497
503
if not datetime_allowed :
498
504
# 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.
501
507
for i in range (len (dt_values )):
502
508
dt_values [i ] = dt_values [i ].isoformat ()
503
509
504
510
return dt_values
505
511
506
512
# 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
513
520
514
- if np and isinstance (obj , np .datetime64 ):
515
- return str (obj )
516
- else :
517
- res = None
521
+ if not datetime_allowed :
518
522
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 ()
523
524
except (TypeError , AttributeError ):
524
525
pass
525
-
526
- if res is not None :
527
- return res
526
+ elif isinstance (obj , datetime .datetime ):
527
+ return obj
528
528
529
529
# Try .tolist() convertible, do not recurse inside
530
530
try :
0 commit comments