[Libreoffice-commits] core.git: wizards/source

Jean-Pierre Ledure (via logerrit) logerrit at kemper.freedesktop.org
Thu Apr 29 09:03:37 UTC 2021


 wizards/source/scriptforge/SF_PythonHelper.xba   |   37 +++++--
 wizards/source/scriptforge/python/scriptforge.py |  116 ++++++++++++++---------
 2 files changed, 101 insertions(+), 52 deletions(-)

New commits:
commit 225ee785520bbbee5b2d9bd63915db7197ee7ccc
Author:     Jean-Pierre Ledure <jp at ledure.be>
AuthorDate: Wed Apr 28 17:16:43 2021 +0200
Commit:     Jean-Pierre Ledure <jp at ledure.be>
CommitDate: Thu Apr 29 11:02:47 2021 +0200

    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 at ledure.be>
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <jp at ledure.be>

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


More information about the Libreoffice-commits mailing list