2022-10-12 20:18:22 +00:00
import datetime
2022-03-16 02:52:54 +00:00
import typing
2023-04-12 20:34:43 +00:00
from hydrus . core import HydrusConstants as HC
2023-04-19 20:38:13 +00:00
from hydrus . core import HydrusGlobals as HG
2023-04-12 20:34:43 +00:00
from hydrus . core import HydrusSerialisable
2023-04-19 20:38:13 +00:00
from hydrus . client import ClientConstants as CC
2024-02-14 21:20:24 +00:00
from hydrus . client import ClientGlobals as CG
2023-04-19 20:38:13 +00:00
2022-10-15 20:01:49 +00:00
try :
from dateutil . relativedelta import relativedelta
DATEUTIL_OK = True
except :
DATEUTIL_OK = False
2023-04-19 20:38:13 +00:00
from hydrus . core import HydrusTime
2022-10-12 20:18:22 +00:00
2023-09-13 18:26:31 +00:00
try :
import dateparser
DATEPARSER_OK = True
except :
DATEPARSER_OK = False
2022-10-12 20:18:22 +00:00
def CalendarDelta ( dt : datetime . datetime , month_delta = 0 , day_delta = 0 ) - > datetime . datetime :
2022-10-15 20:01:49 +00:00
if DATEUTIL_OK :
delta = relativedelta ( months = month_delta , days = day_delta )
return dt + delta
else :
total_days = ( 30 * month_delta ) + day_delta
return dt + datetime . timedelta ( days = total_days )
2022-10-12 20:18:22 +00:00
2023-09-13 18:26:31 +00:00
def ParseDate ( date_string : str ) :
if not DATEPARSER_OK :
raise Exception ( ' Sorry, you need the dateparse library for this, please try reinstalling your venv! ' )
dt = dateparser . parse ( date_string )
if dt is None :
raise Exception ( ' Sorry, could not parse that date! ' )
return HydrusTime . DateTimeToTimestamp ( dt )
2022-03-16 02:52:54 +00:00
def MergeModifiedTimes ( existing_timestamp : typing . Optional [ int ] , new_timestamp : typing . Optional [ int ] ) - > typing . Optional [ int ] :
2023-04-12 20:34:43 +00:00
if ShouldUpdateModifiedTime ( existing_timestamp , new_timestamp ) :
2022-03-16 02:52:54 +00:00
return new_timestamp
else :
return existing_timestamp
2022-06-22 20:43:12 +00:00
2023-04-12 20:34:43 +00:00
def ShouldUpdateModifiedTime ( existing_timestamp : int , new_timestamp : typing . Optional [ int ] ) - > bool :
2022-10-12 20:18:22 +00:00
2023-04-19 20:38:13 +00:00
if new_timestamp is None :
2022-10-12 20:18:22 +00:00
return False
2023-04-19 20:38:13 +00:00
if existing_timestamp is None :
2022-10-12 20:18:22 +00:00
return True
# only go backwards, in general
if new_timestamp > = existing_timestamp :
return False
return True
2022-06-22 20:43:12 +00:00
def TimestampIsSensible ( timestamp : typing . Optional [ int ] ) - > bool :
if timestamp is None :
return False
# assume anything too early is a meme and a timestamp parsing conversion error
if timestamp < = 86400 * 7 :
return False
return True
2023-04-12 20:34:43 +00:00
2023-04-19 20:38:13 +00:00
def TimestampToPrettyTimeDelta ( timestamp , just_now_string = ' just now ' , just_now_threshold = 3 , history_suffix = ' ago ' , show_seconds = True , no_prefix = False ) :
2024-02-14 21:20:24 +00:00
if CG . client_controller . new_options . GetBoolean ( ' always_show_iso_time ' ) :
2023-04-19 20:38:13 +00:00
return HydrusTime . TimestampToPrettyTime ( timestamp )
else :
return HydrusTime . BaseTimestampToPrettyTimeDelta ( timestamp , just_now_string = just_now_string , just_now_threshold = just_now_threshold , history_suffix = history_suffix , show_seconds = show_seconds , no_prefix = no_prefix )
HydrusTime . TimestampToPrettyTimeDelta = TimestampToPrettyTimeDelta
2023-04-12 20:34:43 +00:00
REAL_SIMPLE_TIMESTAMP_TYPES = {
HC . TIMESTAMP_TYPE_ARCHIVED ,
HC . TIMESTAMP_TYPE_MODIFIED_FILE
}
SIMPLE_TIMESTAMP_TYPES = {
HC . TIMESTAMP_TYPE_ARCHIVED ,
HC . TIMESTAMP_TYPE_MODIFIED_FILE ,
HC . TIMESTAMP_TYPE_MODIFIED_AGGREGATE
}
FILE_SERVICE_TIMESTAMP_TYPES = {
HC . TIMESTAMP_TYPE_IMPORTED ,
HC . TIMESTAMP_TYPE_DELETED ,
HC . TIMESTAMP_TYPE_PREVIOUSLY_IMPORTED
}
class TimestampData ( HydrusSerialisable . SerialisableBase ) :
SERIALISABLE_TYPE = HydrusSerialisable . SERIALISABLE_TYPE_TIMESTAMP_DATA
SERIALISABLE_NAME = ' Timestamp Data '
2024-01-17 18:57:00 +00:00
SERIALISABLE_VERSION = 2
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
def __init__ ( self , timestamp_type = None , location = None , timestamp_ms : typing . Optional [ typing . Union [ int , float ] ] = None ) :
2023-04-12 20:34:43 +00:00
HydrusSerialisable . SerialisableBase . __init__ ( self )
self . timestamp_type = timestamp_type
self . location = location
2024-01-17 18:57:00 +00:00
self . timestamp_ms = None if timestamp_ms is None else int ( timestamp_ms )
self . timestamp = HydrusTime . SecondiseMS ( self . timestamp_ms ) # TODO: pretty sure I can delete this variable now, but I am currently attempting to fold space using the spice melange and don't want to make a foolish mistake
2023-04-12 20:34:43 +00:00
def __eq__ ( self , other ) :
if isinstance ( other , TimestampData ) :
return self . __hash__ ( ) == other . __hash__ ( )
return NotImplemented
def __hash__ ( self ) :
2024-01-17 18:57:00 +00:00
return ( self . timestamp_type , self . location , self . timestamp_ms ) . __hash__ ( )
2023-04-12 20:34:43 +00:00
2023-04-19 20:38:13 +00:00
def __repr__ ( self ) :
return self . ToString ( )
2023-04-12 20:34:43 +00:00
def _GetSerialisableInfo ( self ) :
if self . timestamp_type in FILE_SERVICE_TIMESTAMP_TYPES :
serialisable_location = self . location . hex ( )
else :
serialisable_location = self . location # str, int, or None
2024-01-17 18:57:00 +00:00
return ( self . timestamp_type , serialisable_location , self . timestamp_ms )
2023-04-12 20:34:43 +00:00
def _InitialiseFromSerialisableInfo ( self , serialisable_info ) :
2024-01-17 18:57:00 +00:00
( self . timestamp_type , serialisable_location , self . timestamp_ms ) = serialisable_info
self . timestamp = HydrusTime . SecondiseMS ( self . timestamp_ms )
2023-04-12 20:34:43 +00:00
if self . timestamp_type in FILE_SERVICE_TIMESTAMP_TYPES :
self . location = bytes . fromhex ( serialisable_location )
else :
self . location = serialisable_location
2024-01-17 18:57:00 +00:00
def _UpdateSerialisableInfo ( self , version , old_serialisable_info ) :
if version == 1 :
( timestamp_type , serialisable_location , timestamp ) = old_serialisable_info
timestamp_ms = HydrusTime . MillisecondiseS ( timestamp )
new_serialisable_info = ( timestamp_type , serialisable_location , timestamp_ms )
return ( 2 , new_serialisable_info )
2023-04-19 20:38:13 +00:00
def ToString ( self ) - > str :
if self . timestamp_type in SIMPLE_TIMESTAMP_TYPES :
type_base = HC . timestamp_type_str_lookup [ self . timestamp_type ]
else :
if self . timestamp_type in FILE_SERVICE_TIMESTAMP_TYPES :
try :
2024-02-14 21:20:24 +00:00
service_string = CG . client_controller . services_manager . GetName ( self . location )
2023-04-19 20:38:13 +00:00
except :
service_string = ' unknown service '
type_base = ' " {} " {} ' . format ( service_string , HC . timestamp_type_str_lookup [ self . timestamp_type ] )
elif self . timestamp_type == HC . TIMESTAMP_TYPE_LAST_VIEWED :
type_base = ' {} {} ' . format ( CC . canvas_type_str_lookup [ self . location ] , HC . timestamp_type_str_lookup [ self . timestamp_type ] )
elif self . timestamp_type == HC . TIMESTAMP_TYPE_MODIFIED_DOMAIN :
type_base = ' " {} " {} ' . format ( self . location , HC . timestamp_type_str_lookup [ self . timestamp_type ] )
else :
type_base = ' unknown timestamp type '
2024-01-17 18:57:00 +00:00
if self . timestamp_ms is None :
2023-04-19 20:38:13 +00:00
# we are a stub, type summary is appropriate
return type_base
else :
2024-01-17 18:57:00 +00:00
return ' {} : {} ' . format ( type_base , HydrusTime . TimestampMSToPrettyTime ( self . timestamp_ms ) )
2023-04-19 20:38:13 +00:00
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICArchivedTime ( timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_ARCHIVED , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICAggregateModifiedTime ( timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_MODIFIED_AGGREGATE , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICDeletedTime ( service_key : bytes , timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_DELETED , location = service_key , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICDomainModifiedTime ( domain : str , timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_MODIFIED_DOMAIN , location = domain , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICFileModifiedTime ( timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_MODIFIED_FILE , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICImportedTime ( service_key : bytes , timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_IMPORTED , location = service_key , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICLastViewedTime ( canvas_type : int , timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_LAST_VIEWED , location = canvas_type , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
2024-01-17 18:57:00 +00:00
def STATICPreviouslyImportedTime ( service_key : bytes , timestamp_ms : int ) - > " TimestampData " :
2023-04-12 20:34:43 +00:00
2024-01-17 18:57:00 +00:00
return TimestampData ( timestamp_type = HC . TIMESTAMP_TYPE_PREVIOUSLY_IMPORTED , location = service_key , timestamp_ms = timestamp_ms )
2023-04-12 20:34:43 +00:00
@staticmethod
def STATICSimpleStub ( timestamp_type : int ) - > " TimestampData " :
return TimestampData ( timestamp_type = timestamp_type )
HydrusSerialisable . SERIALISABLE_TYPES_TO_OBJECT_TYPES [ HydrusSerialisable . SERIALISABLE_TYPE_TIMESTAMP_DATA ] = TimestampData