diff options
author | Jean-Pierre Ledure <jp@ledure.be> | 2021-04-28 17:16:43 +0200 |
---|---|---|
committer | Jean-Pierre Ledure <jp@ledure.be> | 2021-04-29 11:02:47 +0200 |
commit | 225ee785520bbbee5b2d9bd63915db7197ee7ccc (patch) | |
tree | a89d937b8493829a484b564ac30d3ddcbda1782a /wizards/source | |
parent | 5753386c2353ad4866e7c5dd9e8751ccaa58e93c (diff) |
ScriptForge - (scriptforge.py) dates passed as UNO dates
In replacement of the ISO format, to avoid any
misinterpretation of strings containing accidentally
a date,
from now on, dates are exchanged between Basic and Python
as com.sun.star.util.DateTime structures.
The year boundaries are [1900 - 9999].
The code managing the Python-Basic protocol has been changed
on both sides.
The Basic service receives the
- CDateFromUnoDateTime()
- CDateToUnoDateTime()
methods, equivalent with their Basic homonyms.
Change-Id: Ib6ded20c24ff71d3349d242f72bd7b88f69a2661
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114815
Tested-by: Jean-Pierre Ledure <jp@ledure.be>
Tested-by: Jenkins
Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Diffstat (limited to 'wizards/source')
-rw-r--r-- | wizards/source/scriptforge/SF_PythonHelper.xba | 37 | ||||
-rw-r--r-- | wizards/source/scriptforge/python/scriptforge.py | 116 |
2 files changed, 101 insertions, 52 deletions
diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba b/wizards/source/scriptforge/SF_PythonHelper.xba index 46c28293415b..b7d8141325b2 100644 --- a/wizards/source/scriptforge/SF_PythonHelper.xba +++ b/wizards/source/scriptforge/SF_PythonHelper.xba @@ -177,11 +177,15 @@ Check: SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Try: - vDate = SF_Utils._CStrToDate(DateArg) + If VarType(DateArg) = V_OBJECT Then + vDate = CDateFromUnoDateTime(DateArg) + Else + vDate = SF_Utils._CStrToDate(DateArg) + End If vNewDate = DateAdd(Add, Count, vDate) Finally: - If VarType(vNewDate) = V_DATE Then PyDateAdd = SF_Utils._CDateToIso(vNewDate) Else PyDateAdd = vNewDate + If VarType(vNewDate) = V_DATE Then PyDateAdd = CDateToUnoDateTime(vNewDate) Else PyDateAdd = vNewDate SF_Utils._ExitFunction(cstThisSub) Exit Function Catch: @@ -219,8 +223,16 @@ Check: SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Try: - vDate1 = SF_Utils._CStrToDate(Date1) - vDate2 = SF_Utils._CStrToDate(Date2) + If VarType(Date1) = V_OBJECT Then + vDate1 = CDateFromUnoDateTime(Date1) + Else + vDate1 = SF_Utils._CStrToDate(Date1) + End If + If VarType(Date2) = V_OBJECT Then + vDate2 = CDateFromUnoDateTime(Date2) + Else + vDate2 = SF_Utils._CStrToDate(Date2) + End If lDiff = DateDiff(Add, vDate1, vDate2, WeekStart, YearStart) @@ -261,7 +273,11 @@ Check: SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Try: - vDate = SF_Utils._CStrToDate(DateArg) + If VarType(DateArg) = V_OBJECT Then + vDate = CDateFromUnoDateTime(DateArg) + Else + vDate = SF_Utils._CStrToDate(DateArg) + End If lPart = DatePart(Add, vDate, WeekStart, YearStart) @@ -297,7 +313,7 @@ Try: vDate = DateValue(DateArg) Finally: - If VarType(vDate) = V_DATE Then PyDateValue = SF_Utils._CDateToIso(vDate) Else PyDateValue = vDate + If VarType(vDate) = V_DATE Then PyDateValue = CDateToUnoDateTime(vDate) Else PyDateValue = vDate SF_Utils._ExitFunction(cstThisSub) Exit Function Catch: @@ -329,7 +345,7 @@ Check: SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Try: - If VarType(Value) = V_DATE Then vValue = SF_Utils._CStrToDate(Value) ELse vValue = Value + If VarType(Value) = V_OBJECT Then vValue = CDateFromUnoDateTime(Value) ELse vValue = Value If IsEmpty(Pattern) Or Len(Pattern) = 0 Then sFormat = Str(vValue) Else sFormat = Format(vValue, Pattern) @@ -600,10 +616,9 @@ Check: vArg = Null ElseIf vArg = cstSymMissing Then Exit For ' Next arguments must be missing also - ElseIf ( CallType And cstDateArg ) = cstDateArg Then ' Arguments might be dates - vArg = SF_Utils._CStrToDate(vArg) - If vArg < 0 Then vArg = Args(i) ' Conversion of iso format failed => reset End If + ElseIf VarType(vArg) = V_OBJECT Then + If ( CallType And cstDateArg ) = cstDateArg Then vArg = CDateFromUnoDateTime(vArg) End If iNbArgs = iNbArgs + 1 @@ -810,7 +825,7 @@ Try: End If Else ' Scalar or Nothing ReDim vReturnArray(0 To 1) - If VarType(vReturn) = V_DATE Then vReturnArray(0) = SF_Utils._CDateToIso(vReturn) Else vReturnArray(0) = vReturn + If VarType(vReturn) = V_DATE Then vReturnArray(0) = CDateToUnoDateTime(vReturn) Else vReturnArray(0) = vReturn vReturnArray(1) = VarType(vReturn) End If diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index bcd047ba7fa1..6c65f73d00ca 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -57,6 +57,7 @@ import uno import datetime +import time import os @@ -318,11 +319,8 @@ class ScriptForge(object, metaclass = _Singleton): if isinstance(returntuple[cstValue], uno.ByteSequence): return () elif returntuple[cstVarType] == ScriptForge.V_DATE: - dat = None - try: # Anticipate fromisoformat('00:00:00') and alike - dat = datetime.datetime.fromisoformat(returntuple[cstValue]) - finally: - return dat + dat = SFScriptForge.SF_Basic.CDateFromUnoDateTime(returntuple[cstValue]) + return dat else: # All other scalar values pass return returntuple[cstValue] @@ -562,9 +560,13 @@ class SFServices(object): Set the given property to a new value in the Basic world """ if self.serviceimplementation == 'basic': + flag = self.vbLet if isinstance(value, datetime.datetime): - value = value.isoformat() - return self.EXEC(self.objectreference, self.vbLet + self.flgDateArg, propertyname, value) + value = SFScriptForge.SF_Basic.CDateToUnoDateTime(value) + flag += self.flgDateArg + if repr(type(value)) == "<class 'pyuno'>": + flag += self.flgUno + return self.EXEC(self.objectreference, flag, propertyname, value) # ##################################################################################################################### @@ -622,6 +624,61 @@ class SFScriptForge: MB_OK, MB_OKCANCEL, MB_RETRYCANCEL, MB_YESNO, MB_YESNOCANCEL = 0, 1, 5, 4, 3 IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES = 3, 2, 5, 7, 1, 4, 6 + @staticmethod + def CDateFromUnoDateTime(unodate): + """ + Converts a UNO date/time representation to a datetime.datetime Python native object + :param unodate: com.sun.star.util.DateTime, com.sun.star.util.Date or com.sun.star.util.Time + :return: the equivalent datetime.datetime + """ + date = datetime.datetime(1899, 12, 30, 0, 0, 0, 0) # Idem as Basic builtin TimeSeria() function + datetype = repr(type(unodate)) + if 'com.sun.star.util.DateTime' in datetype: + if 1900 <= unodate.Year <= datetime.MAXYEAR: + date = datetime.datetime(unodate.Year, unodate.Month, unodate.Day, unodate.Hours, + unodate.Minutes, unodate.Seconds, int(unodate.NanoSeconds / 1000)) + elif 'com.sun.star.util.Date' in datetype: + if 1900 <= unodate.Year <= datetime.MAXYEAR: + date = datetime.datetime(unodate.Year, unodate.Month, unodate.Day) + elif 'com.sun.star.util.Time' in datetype: + date = datetime.datetime(unodate.Hours, unodate.Minutes, unodate.Seconds, + int(unodate.NanoSeconds / 1000)) + else: + return unodate # Not recognized as a UNO date structure + return date + + @staticmethod + def CDateToUnoDateTime(date): + """ + Converts a date representation into the ccom.sun.star.util.DateTime date format + Acceptable boundaries: year >= 1900 and <= 32767 + :param date: datetime.datetime, datetime.date, datetime.time, float (time.time) or time.struct_time + :return: a com.sun.star.util.DateTime + """ + unodate = uno.createUnoStruct('com.sun.star.util.DateTime') + unodate.Year, unodate.Month, unodate.Day, unodate.Hours, unodate.Minutes, unodate.Seconds, \ + unodate.NanoSeconds, unodate.IsUTC = \ + 1899, 12, 30, 0, 0, 0, 0, False # Identical to Basic TimeSerial() function + + if isinstance(date, float): + date = time.localtime(date) + if isinstance(date, time.struct_time): + if 1900 <= date[0] <= 32767: + unodate.Year, unodate.Month, unodate.Day, unodate.Hours, unodate.Minutes, unodate.Seconds =\ + date[0:6] + else: # Copy only the time related part + unodate.Hours, unodate.Minutes, unodate.Seconds = date[3:3] + elif isinstance(date, (datetime.datetime, datetime.date, datetime.time)): + if isinstance(date, (datetime.datetime, datetime.date)): + if 1900 <= date.year <= 32767: + unodate.Year, unodate.Month, unodate.Day = date.year, date.month, date.day + if isinstance(date, (datetime.datetime, datetime.time)): + unodate.Hours, unodate.Minutes, unodate.Seconds, unodate.NanoSeconds = \ + date.hour, date.minute, date.second, date.microsecond * 1000 + else: + return date # Not recognized as a date + return unodate + @classmethod def ConvertFromUrl(cls, url): return cls.SIMPLEEXEC(cls.module + '.PyConvertFromUrl', url) @@ -637,22 +694,22 @@ class SFScriptForge: @classmethod def DateAdd(cls, interval, number, date): if isinstance(date, datetime.datetime): - date = date.isoformat() + date = cls.CDateToUnoDateTime(date) dateadd = cls.SIMPLEEXEC(cls.module + '.PyDateAdd', interval, number, date) - return datetime.datetime.fromisoformat(dateadd) + return cls.CDateFromUnoDateTime(dateadd) @classmethod def DateDiff(cls, interval, date1, date2, firstdayofweek = 1, firstweekofyear = 1): if isinstance(date1, datetime.datetime): - date1 = date1.isoformat() + date1 = cls.CDateToUnoDateTime(date1) if isinstance(date2, datetime.datetime): - date2 = date2.isoformat() + date2 = cls.CDateToUnoDateTime(date2) return cls.SIMPLEEXEC(cls.module + '.PyDateDiff', interval, date1, date2, firstdayofweek, firstweekofyear) @classmethod def DatePart(cls, interval, date, firstdayofweek = 1, firstweekofyear = 1): if isinstance(date, datetime.datetime): - date = date.isoformat() + date = cls.CDateToUnoDateTime(date) return cls.SIMPLEEXEC(cls.module + '.PyDatePart', interval, date, firstdayofweek, firstweekofyear) @classmethod @@ -660,12 +717,12 @@ class SFScriptForge: if isinstance(string, datetime.datetime): string = string.isoformat() datevalue = cls.SIMPLEEXEC(cls.module + '.PyDateValue', string) - return datetime.datetime.fromisoformat(datevalue) + return cls.CDateFromUnoDateTime(datevalue) @classmethod def Format(cls, expression, format = ''): if isinstance(expression, datetime.datetime): - expression = expression.isoformat() + expression = cls.CDateToUnoDateTime(expression) return cls.SIMPLEEXEC(cls.module + '.PyFormat', expression, format) @classmethod @@ -770,30 +827,6 @@ class SFScriptForge: The resulting array is empty when the dictionary is empty. """ - def CDateToUno(date): - """ - Converts a datetime object into the corresponding com.sun.star.util.x date format - :param date: datetime.datetime, date or time - :return: a com.sun.star.util.DateTime, Date or Time - """ - pvdate = None - if isinstance(date, datetime.datetime): - pvdate = uno.createUnoStruct('com.sun.star.util.DateTime') - elif isinstance(date, datetime.date): - pvdate = uno.createUnoStruct('com.sun.star.util.Date') - elif isinstance(date, datetime.time): - pvdate = uno.createUnoStruct('com.sun.star.util.Time') - if isinstance(date, (datetime.datetime, datetime.date)): - pvdate.Year = date.year - pvdate.Month = date.month - pvdate.Day = date.day - if isinstance(date, (datetime.datetime, datetime.time)): - pvdate.Hours = date.hour - pvdate.Minutes = date.minute - pvdate.Seconds = date.second - pvdate.NanoSeconds = date.microsecond - return pvdate - result = [] for key in iter(self): value = self[key] @@ -809,7 +842,7 @@ class SFScriptForge: value[i] = None item = value elif isinstance(value, (datetime.datetime, datetime.date, datetime.time)): - item = CDateToUno(value) + item = SFScriptForge.SF_Basic.CDateToUnoDateTime(value) pv = uno.createUnoStruct('com.sun.star.beans.PropertyValue') pv.Name = key pv.Value = item @@ -820,6 +853,7 @@ class SFScriptForge: """ nserts the contents of an array of PropertyValue objects into the current dictionary. PropertyValue Names are used as keys in the dictionary, whereas Values contain the corresponding values. + Date-type values are converted to datetime.datetime instances. :param propertyvalues: a list.tuple containing com.sun.star.beans.PropertyValue objects :param overwrite: When True, entries with same name may exist in the dictionary and their values are overwritten. When False (default), repeated keys are not overwritten. @@ -832,11 +866,11 @@ class SFScriptForge: item = pv.Value if 'com.sun.star.util.DateTime' in repr(type(item)): item = datetime.datetime(item.Year, item.Month, item.Day, - item.Hours, item.Minutes, item.Seconds, item.NanoSeconds) + item.Hours, item.Minutes, item.Seconds, int(item.NanoSeconds / 1000)) elif 'com.sun.star.util.Date' in repr(type(item)): item = datetime.datetime(item.Year, item.Month, item.Day) elif 'com.sun.star.util.Time' in repr(type(item)): - item = datetime.datetime(item.Hours, item.Minutes, item.Seconds, item.NanoSeconds) + item = datetime.datetime(item.Hours, item.Minutes, item.Seconds, int(item.NanoSeconds / 1000)) result.append((key, item)) self.update(result) return True |