mirror of
https://github.com/apache/superset.git
synced 2026-05-02 14:34:22 +00:00
Compare commits
1 Commits
docs/testi
...
fix/mssql-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4026ac9134 |
@@ -19,6 +19,11 @@ from datetime import datetime
|
|||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
EPOCH = datetime(1970, 1, 1)
|
EPOCH = datetime(1970, 1, 1)
|
||||||
|
# JavaScript's Date object can safely represent dates within this range
|
||||||
|
# These are the min/max values that can be represented as milliseconds since epoch
|
||||||
|
# without overflowing JavaScript's Number type (±2^53)
|
||||||
|
JS_DATE_RANGE_MIN = datetime(1938, 4, 24, 22, 13, 20, 0)
|
||||||
|
JS_DATE_RANGE_MAX = datetime(2286, 11, 20, 17, 46, 39, 999000)
|
||||||
|
|
||||||
|
|
||||||
def datetime_to_epoch(dttm: datetime) -> float:
|
def datetime_to_epoch(dttm: datetime) -> float:
|
||||||
|
|||||||
@@ -29,7 +29,12 @@ from jsonpath_ng import parse
|
|||||||
from simplejson import JSONDecodeError
|
from simplejson import JSONDecodeError
|
||||||
|
|
||||||
from superset.constants import PASSWORD_MASK
|
from superset.constants import PASSWORD_MASK
|
||||||
from superset.utils.dates import datetime_to_epoch, EPOCH
|
from superset.utils.dates import (
|
||||||
|
datetime_to_epoch,
|
||||||
|
EPOCH,
|
||||||
|
JS_DATE_RANGE_MAX,
|
||||||
|
JS_DATE_RANGE_MIN,
|
||||||
|
)
|
||||||
|
|
||||||
logging.getLogger("MARKDOWN").setLevel(logging.INFO)
|
logging.getLogger("MARKDOWN").setLevel(logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -155,9 +160,27 @@ def json_int_dttm_ser(obj: Any) -> Any:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(obj, (datetime, pd.Timestamp)):
|
if isinstance(obj, (datetime, pd.Timestamp)):
|
||||||
|
# Check if datetime is within JavaScript's safe date range
|
||||||
|
# If not, return ISO string instead of epoch milliseconds
|
||||||
|
if isinstance(obj, pd.Timestamp):
|
||||||
|
dttm = obj.to_pydatetime()
|
||||||
|
else:
|
||||||
|
dttm = obj
|
||||||
|
|
||||||
|
# Remove timezone info for comparison
|
||||||
|
dttm_no_tz = dttm.replace(tzinfo=None) if dttm.tzinfo else dttm
|
||||||
|
|
||||||
|
if dttm_no_tz < JS_DATE_RANGE_MIN or dttm_no_tz > JS_DATE_RANGE_MAX:
|
||||||
|
# Return ISO string for dates outside JavaScript's safe range
|
||||||
|
return obj.isoformat()
|
||||||
|
|
||||||
return datetime_to_epoch(obj)
|
return datetime_to_epoch(obj)
|
||||||
|
|
||||||
if isinstance(obj, date):
|
if isinstance(obj, date):
|
||||||
|
# Check if date is within JavaScript's safe date range
|
||||||
|
date_as_datetime = datetime.combine(obj, datetime.min.time())
|
||||||
|
if date_as_datetime < JS_DATE_RANGE_MIN or date_as_datetime > JS_DATE_RANGE_MAX:
|
||||||
|
return obj.isoformat()
|
||||||
return (obj - EPOCH.date()).total_seconds() * 1000
|
return (obj - EPOCH.date()).total_seconds() * 1000
|
||||||
|
|
||||||
return base_json_conv(obj)
|
return base_json_conv(obj)
|
||||||
|
|||||||
@@ -254,6 +254,23 @@ def test_json_int_dttm_ser():
|
|||||||
assert json.json_int_dttm_ser(dttm + timedelta(milliseconds=1)) == (ts + 1)
|
assert json.json_int_dttm_ser(dttm + timedelta(milliseconds=1)) == (ts + 1)
|
||||||
assert json.json_int_dttm_ser(np.int64(1)) == 1
|
assert json.json_int_dttm_ser(np.int64(1)) == 1
|
||||||
|
|
||||||
|
# Test edge cases for JavaScript Date range
|
||||||
|
# Dates outside JavaScript's safe range should return ISO strings
|
||||||
|
assert (
|
||||||
|
json.json_int_dttm_ser(datetime(1938, 4, 24, 22, 13, 19))
|
||||||
|
== "1938-04-24T22:13:19"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
json.json_int_dttm_ser(datetime(2286, 11, 20, 17, 46, 40))
|
||||||
|
== "2286-11-20T17:46:40"
|
||||||
|
)
|
||||||
|
assert json.json_int_dttm_ser(date(1938, 4, 23)) == "1938-04-23"
|
||||||
|
assert json.json_int_dttm_ser(date(2286, 11, 21)) == "2286-11-21"
|
||||||
|
|
||||||
|
# Dates within JavaScript's safe range should return epoch milliseconds
|
||||||
|
assert isinstance(json.json_int_dttm_ser(datetime(2000, 1, 1)), (int, float))
|
||||||
|
assert isinstance(json.json_int_dttm_ser(date(2000, 1, 1)), (int, float))
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
json.json_int_dttm_ser(np.datetime64())
|
json.json_int_dttm_ser(np.datetime64())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user