#-----------------------------------------------------------------------------# Copyright (c) Anaconda, Inc., and Bokeh Contributors.# All rights reserved.## The full license is in the file LICENSE.txt, distributed with this software.#-----------------------------------------------------------------------------""" Provide date and time related properties"""#-----------------------------------------------------------------------------# Boilerplate#-----------------------------------------------------------------------------from__future__importannotationsimportlogging# isort:skiplog=logging.getLogger(__name__)#-----------------------------------------------------------------------------# Imports#-----------------------------------------------------------------------------# Standard library importsimportdatetimefromtypingimportAny# Bokeh importsfrom...util.serializationimport(convert_date_to_datetime,is_datetime_type,is_timedelta_type,)from.basesimportInit,Propertyfrom.primitiveimportbokeh_integer_typesfrom.singletonsimportUndefined#-----------------------------------------------------------------------------# Globals and constants#-----------------------------------------------------------------------------__all__=('Date','Datetime','Time','TimeDelta',)#-----------------------------------------------------------------------------# General API#-----------------------------------------------------------------------------
[docs]classDate(Property[str|datetime.date]):""" Accept ISO format Date (but not DateTime) values. """deftransform(self,value:Any)->Any:value=super().transform(value)ifisinstance(value,datetime.date):value=value.isoformat()returnvaluedefvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)# datetime.datetime is datetime.date, exclude manually up frontifisinstance(value,datetime.datetime):msg=""ifnotdetailelse"Expected a date value, got a datetime.datetime"raiseValueError(msg)ifisinstance(value,datetime.date):returntry:datetime.datetime.fromisoformat(value)exceptException:msg=""ifnotdetailelsef"Expected an ISO date string, got {value!r}"raiseValueError(msg)
[docs]classDatetime(Property[str|datetime.date|datetime.datetime]):""" Accept ISO format Datetime values. """def__init__(self,default:Init[str|datetime.date|datetime.datetime]=Undefined,*,help:str|None=None)->None:super().__init__(default=default,help=help)deftransform(self,value:Any)->Any:value=super().transform(value)ifisinstance(value,str):value=datetime.datetime.fromisoformat(value)# Handled by serialization in protocol.py for now, except for Dateifisinstance(value,datetime.date):value=convert_date_to_datetime(value)returnvaluedefvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifis_datetime_type(value):returnifisinstance(value,datetime.date):returnifDatetime.is_timestamp(value):returnifisinstance(value,str):try:datetime.datetime.fromisoformat(value).date()returnexceptException:passmsg=""ifnotdetailelsef"Expected a date, datetime object, or timestamp, got {value!r}"raiseValueError(msg)@staticmethoddefis_timestamp(value:Any)->bool:returnisinstance(value,(float,*bokeh_integer_types))andnotisinstance(value,bool)
[docs]classTime(Property[str|datetime.time]):""" Accept ISO format time values. """def__init__(self,default:Init[str|datetime.time]=Undefined,*,help:str|None=None)->None:super().__init__(default=default,help=help)defvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifisinstance(value,datetime.time):returnifisinstance(value,str):try:datetime.time.fromisoformat(value)returnexceptValueError:passmsg=""ifnotdetailelsef"Expected a time object, or ISO formatted time string, got {value!r}"raiseValueError(msg)deftransform(self,value:Any)->Any:value=super().transform(value)ifisinstance(value,str):value=datetime.time.fromisoformat(value)returnvalue
[docs]classTimeDelta(Property[datetime.timedelta]):""" Accept TimeDelta values. """def__init__(self,default:Init[datetime.timedelta]=datetime.timedelta(),*,help:str|None=None)->None:super().__init__(default=default,help=help)deftransform(self,value:Any)->Any:value=super().transform(value)returnvalue# Handled by serialization in protocol.py for nowdefvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifis_timedelta_type(value):returnmsg=""ifnotdetailelsef"Expected a timedelta instance, got {value!r}"raiseValueError(msg)
#-----------------------------------------------------------------------------# Dev API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Private API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Code#-----------------------------------------------------------------------------