2022-10-12 20:18:22 +00:00
|
|
|
import datetime
|
|
|
|
import time
|
2022-03-16 02:52:54 +00:00
|
|
|
import typing
|
|
|
|
|
2022-10-15 20:01:49 +00:00
|
|
|
try:
|
|
|
|
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
|
|
|
|
DATEUTIL_OK = True
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
DATEUTIL_OK = False
|
|
|
|
|
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
from hydrus.core import HydrusData
|
|
|
|
|
|
|
|
def CalendarToTimestamp( dt: datetime.datetime ) -> int:
|
2022-03-09 22:18:23 +00:00
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
try:
|
2022-03-09 22:18:23 +00:00
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
# mktime is local calendar time to timestamp, so this is client specific
|
|
|
|
timestamp = int( time.mktime( dt.timetuple() ) )
|
2022-03-09 22:18:23 +00:00
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
except:
|
2022-06-22 20:43:12 +00:00
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
timestamp = HydrusData.GetNow()
|
2022-06-22 20:43:12 +00:00
|
|
|
|
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
return timestamp
|
2022-03-09 22:18:23 +00:00
|
|
|
|
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-02-22 21:57:10 +00:00
|
|
|
def GetDateTime( year: int, month: int, day: int, hour: int, minute: int ) -> datetime.datetime:
|
2022-10-12 20:18:22 +00:00
|
|
|
|
2023-02-22 21:57:10 +00:00
|
|
|
return datetime.datetime( year, month, day, hour, minute )
|
2022-03-16 02:52:54 +00:00
|
|
|
|
|
|
|
def MergeModifiedTimes( existing_timestamp: typing.Optional[ int ], new_timestamp: typing.Optional[ int ] ) -> typing.Optional[ int ]:
|
|
|
|
|
2022-06-22 20:43:12 +00:00
|
|
|
if not TimestampIsSensible( existing_timestamp ):
|
2022-03-16 02:52:54 +00:00
|
|
|
|
2022-06-22 20:43:12 +00:00
|
|
|
existing_timestamp = None
|
2022-03-16 02:52:54 +00:00
|
|
|
|
|
|
|
|
2022-06-22 20:43:12 +00:00
|
|
|
if not TimestampIsSensible( new_timestamp ):
|
2022-03-16 02:52:54 +00:00
|
|
|
|
2022-06-22 20:43:12 +00:00
|
|
|
new_timestamp = None
|
2022-03-16 02:52:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
if ShouldUpdateDomainModifiedTime( existing_timestamp, new_timestamp ):
|
|
|
|
|
|
|
|
return new_timestamp
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return existing_timestamp
|
|
|
|
|
|
|
|
|
2022-06-22 20:43:12 +00:00
|
|
|
|
2022-10-12 20:18:22 +00:00
|
|
|
def ShouldUpdateDomainModifiedTime( existing_timestamp: int, new_timestamp: typing.Optional[ int ] ) -> bool:
|
|
|
|
|
|
|
|
if not TimestampIsSensible( new_timestamp ):
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
if not TimestampIsSensible( existing_timestamp ):
|
|
|
|
|
|
|
|
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
|
|
|
|
|