@Lupp
I took what you posted and changed it for my needs so that UTC offset is standard and allows two digit hours while also ensuring the offset is properly rounded. Here it is for anyone who wants to ensure timezone offset correctness with this forsaken language. I am interested in critique, if this could be improved, if somebody gets an incorrectly calculated or rounded timezone, etc… This assumes that timezone offsets will have 15 minute offsets and more explanation in the comments.
REM ***** BASIC *****
Option Explicit
Function localDateTimeOffset(pMode As Integer)
Dim utcPrefix As String
If (pMode = 0) Then
utcPrefix = ""
ElseIf (pMode = 1) Then
utcPrefix = " UTC"
Else
MsgBox("localDateTimeOffset requires 1 for UTC prefix string or 0 for none")
Stop
EndIf
Dim aLocale As New com.sun.star.lang.Locale
Dim oLocaleCalendar As Object
Dim offset As Double
Dim fixedOffset As Double
Dim result
Dim signChar
oLocaleCalendar = CreateUnoService("com.sun.star.i18n.LocaleCalendar")
With oLocaleCalendar
.loadDefaultCalendar(aLocale) REM Uses Unix NullDate!
'.LocalDateTime is time local to user. .DateTime is UTC standard time.
'Formatting these two will see this. These are not documented functions.
'May cause rounding issues if second function lags too much
offset = .LocalDateTime - .DateTime
End With
'Some tests you can run by uncommenting and respective expected results
'offset = -0.332916666667 '7.99/24 -8:00
'offset = -0.304166666667 '7.3/24 -7:30
'offset = -0.295833333333 '7.1/24 -7:15
'offset = -0.291666666667 '7.0/24 -7:00
'offset = -0.3125 '7.5/24 -7:30
'offset = -0.520833333333 '12.5/24 -12:30
'offset = 0.691666666667 '16.6/24 +16:45:
'offset = -0.5 '12.0/24 -12:00
'offset = 0 '0.0/24 +00:00
signChar = IIf(sgn(offset)<0,"-", "+") 'Get sign indicating offset is behind or ahead of UTC to prepend to output
'Format and other functions round number so need to make sure time is properly rounded.
'Assuming timezone works in 15 minute increments (that's what the UTC offset wikipedia article says) and the datetime functions were designed with
'that assumptiom, this will make sure the offset is rounded to the intended 15 minute increment.
fixedOffset = fracCeiling(offset * 24, 15)
'HH:MM is not used because it rounds and/or doesn't round when it shouldn't
result = utcPrefix & signChar & Replace(Format(fixedOffset, "00.00"), ".", ":")
localDateTimeOffset = result
End Function
Function fracCeiling(offset As Double, increment As Double) As Double
Dim oService As Object
Dim offsetAbs As Double
Dim integerPortion As Double
Dim mantissaLowRes As Double
Dim mantissa As Double
Dim offsetRounded As Double
Dim mantissaRounded As Double
Dim result As Double
If (increment * 100 = 0) Then
MsgBox("Divide by 0 error! Time multiple can't be 0!")
Stop
EndIf
offsetAbs = Abs(offset) 'Make sure offset is positive
integerPortion = Fix(offsetAbs) 'Remove mantissa from offset
mantissaLowRes = CDbl(Format(offsetAbs, ".000")) 'Reduce precision of offset to stop unnecessary rounding
mantissa = mantissaLowRes - integerPortion 'Get the mantissa from the offset
oService = createUnoService("com.sun.star.sheet.FunctionAccess")
offsetRounded = oService.CallFunction("ISO.CEILING", Array(offsetAbs, increment / 60 )) 'Make sure the hour is rounded correctly
mantissaRounded = (oService.CallFunction("ISO.CEILING", Array(mantissa, increment / 60)) * 60) / 100 'Round the mantissa separately so it can be converted to minutes
if (mantissaRounded = .6) Then 'So that offset at ?:00 isn't ?:60
mantissaRounded = 0
EndIf
result = Fix(offsetRounded) + mantissaRounded 'Add rounded offset and mantissa back together
fracCeiling=result
End Function
Sub TestFunction
MsgBox(localDateTimeOffset(1))
End Sub
.
Remaining question about the API:
Why does creating UnoService com.sun.star.i18n.LocaleCalendar
also create/import com.sun.star.i18n.LocaleCalendar2
and inherit functions from it as indicated by MRI and testing inherited functions myself?