SysTime- Library

Filippo

Expert
Licensed User
Hi,

SysTime is a small library to get and set the current system time and system date.
There are two different dll's, one for the desktop and one for the device.

20.09.2009: Version 1.01


Ciao.
Filippo
 

Attachments

Last edited:

alfcen

Well-Known Member
Licensed User
Ciao Filippo,
Execellent! Awesome!

Thanks to your DLL, I can set the clock with GPS date and time.
Here is the source for everybody. Perhaps someone can shorten it :)

B4X:
'Requires Registry DLL (object reg), Bitwise DLL (object bit) and Filippo's SysTime DLL (object SysTime)

Sub Globals
  Dim zti(0) As Byte  'binary array for GetTimeZone
End Sub

Sub App_Start
  Reg.New1
  SysTime.New1
End Sub

Sub mnuSetSystemDateTime_Click
  If GPS.Status<>"A" Then Return    'Aborts if no stable GPS signal present
  'GPS.UTCDate and GPS.UTCTime available from Sub GPS_GPSDecoded. Please see gps.dll Help for details
  Dim x, y, i, zt
  zt = GetTimeZone
  x = DateParse(GPS2Date(GPS.UTCDate))
  y = TimeParse(GPS2Time(GPS.UTCTime)) + zt/24 * cTicksPerDay      'add your local time zone
  i = Msgbox("GPS date and time converted to local is " & CrLf & Date(x) & " " & Time(y) & CrLf & "Set the device?"," Confirmation",cMsgBoxYesNo,cMsgBoxQuestion)
  If i = cNo Then Return
  ErrorLabel(SetError)            'There is no success flag in the SysTime DLL
  SysTime.New1
  Systime.SetDate(DateMonth(x),DateDay(x),DateYear(x))
  Systime.SetTime(TimeHour(y),TimeMinute(y),TimeSecond(y))
  Msgbox("GPS Date and Time set."," GPS Date and Time",cMsgBoxNone,cMsgBoxAsterisk)   
  Return
SetError:
  Msgbox("Error setting Date and Time."," GPS Date and Time",cMsgBoxNone,cMsgBoxHand)
End Sub

Sub GPS2Time(x)
  Dim colon
  TimeFormat("HH:mm:ss")
  colon=SubString(x,0,6)
  colon=StrInsert(colon,2,":")
  colon=StrInsert(colon,5,":")
  x = TimeParse(colon)
  if chkAMPM.Checked=True Then TimeFormat("hh:mm:ss tt")  'A check box selects EU or US format
  Return Time(x)
End Sub

Sub GPS2Date(x)
  Dim dash
  DateFormat ("yyyy/mm/dd")
  dash="20" & SubString(x,4,2) & "/"
  dash=dash & SubString(x,2,2) & "/"
  dash=dash & SubString(x,0,2)
  x = DateParse(dash)
  if chkAMPM.Checked=false then    'A check box selects EU or US format
    DateFormat("dd/mm/yyyy")
  else
    DateFormat("mm/dd/yyyy")
  End if 
  Return Date(x)
End Sub

Sub GetTimeZone
  Dim m, i, b
  Reg.RootKey(Reg.rtLocalMachine)
  If cPPC = True Then
    zti()=Reg.GetValue("Time","TimeZoneInformation")
    For i = 3 To 0 Step -1
      m = m & bit.DecToHex(zti(i))
    Next
    m = bit.HexToDec(m) / 60 * (-1)
  Else
    m = Reg.GetValue("System\CurrentControlSet\Control\TimeZoneInformation","ActiveTimeBias")
    m = m  / 60 * (-1)
  End If
  If m > 0 Then m = "+" & m
  Return m   
End Sub
 

alfcen

Well-Known Member
Licensed User
Correction

Sorry gents,
There is an error in
mnuSetSystemDateTime_Click
which I have corrected as:

B4X:
Sub mnuSetSystemDateTime_Click
  If GPS.Status="A" Then
    Dim x, i
    x =DateParse(GPS2Time(GPS.UTCTime))   'addition of time zone must account for date change
    x = x - x Mod cTicksPerDay 
    x = x + TimeParse(GPS2Time(GPS.UTCTime)) + zt * cTicksPerHour
    i = Msgbox("GPS date and time converted to local is " & CrLf & Date(x) & " " & Time(x) & CrLF & "Set the device?"," Confirmation",cMsgBoxYesNo,cMsgBoxQuestion)
    If i = cNo Then Return
    ErrorLabel(SetError)
    SysTime.New1
    Systime.SetDate(DateMonth(x),DateDay(x),DateYear(x))
    Systime.SetTime(TimeHour(x),TimeMinute(x),TimeSecond(x))
    Msgbox("GPS Date and Time set."," GPS Date and Time",cMsgBoxNone,cMsgBoxAsterisk)   
    Return
SetError:
    Msgbox("Error setting Date and Time."," GPS Date and Time",cMsgBoxNone,cMsgBoxHand)
  Else
    Msgbox("GPS data unstable or not available."," GPS Status",cMsgBoxNone,cMsgBoxHand)
    Return
  End If      
End Sub
 

derez

Expert
Licensed User
Thanks Filippo
It's already integrated and working in my navigation program.:)
 

Zenerdiode

Active Member
Licensed User
Error in help

Hi Filippo,

I think there is an error in your help file for SetDate

Syntax: SetDate(Day As Integer, Month As Integer, Year As Integer)
Its looking as if the Day and Month are swapped i.e. it should read:
Syntax: SetDate(Month As Integer, Day As Integer, Year As Integer) :)

Edit: "Does anyone know how to set the BIOS date & time in the Desktop?" I see that it does!
 
Last edited:

mjcoon

Well-Known Member
Licensed User
B4X:
Sub mnuSetSystemDateTime_Click
...
    i = Msgbox("GPS date and time converted to local is " & CrLf & Date(x) & " " & Time(x) & CrLF & "Set the device?"," Confirmation",cMsgBoxYesNo,cMsgBoxQuestion)
...
    Return
nd Sub
It's not ideal to ask the user a question and then set the time to what was determined before asking the question.

In a Psion program that I wrote years ago to do this I showed the disparity when asking the question (as well as GPS and system times) and then if the user requested time alteration I adjusted the system time by the disparity amount. This is then independent of the user's decision time...
 

mjcoon

Well-Known Member
Licensed User
Hi,

SysTime is a small library to get and set the current system time and system date.
There are two different dll's, one for the desktop and one for the device.

Ciao.
Filippo
This looks jolly useful (surprising it is not already included in other libraries!).

But when I add the DLLs I get offered objects of type "SysTime" (as I expected) but also "SYSTEMTIME". What is the difference, please (and how to remember the distinction; it's not in the Help!).

Mike.
 

mjcoon

Well-Known Member
Licensed User
Ciao Filippo,
Execellent! Awesome!

Thanks to your DLL, I can set the clock with GPS date and time.
Here is the source for everybody. Perhaps someone can shorten it :)

B4X:
...

Sub GetTimeZone
  Dim m, i, b
  Reg.RootKey(Reg.rtLocalMachine)
  If cPPC = True Then
    zti()=Reg.GetValue("Time","TimeZoneInformation")
    For i = 3 To 0 Step -1
      m = m & bit.DecToHex(zti(i))
    Next
    m = bit.HexToDec(m) / 60 * (-1)
  Else
    m = Reg.GetValue("System\CurrentControlSet\Control\TimeZoneInformation","ActiveTimeBias")
    m = m  / 60 * (-1)
  End If
  If m > 0 Then m = "+" & m
  Return m   
End Sub
I guess all that stuff with DecToHex and HexToDec is just to convert 4 bytes to a 32-bit integer. Which could be done with some *256 or neatly with the ByteConverter DLL using Int32FromBytes().

But reading the registry item separately on my PDA gives four zeroes (but lots of other following bytes; goodness knows what they mean!). This is fair enough since I am in Zulu time zone. But I am also in daylight saving time, so where would that other hour correction come from?

Mike.
 

agraham

Expert
Licensed User
lots of other following bytes; goodness knows what they mean!
I suspect they contain the DST information for the time zone.

SYSTEMTIME
That is a struct definition that shouldn't really be visible. An instance of it is passed to the OS to set or get the time and date information. It is of no use as a Basic4ppc object.

@Filippo - how about hiding "SYSTEMTIME" by renaming it "_SYSTEMTIME" and providing the sources for merging?
 
Last edited:

mjcoon

Well-Known Member
Licensed User
I suspect they contain the DST information for the time zone.
Ah, yes, I'm sure you are right, and I can see "GMT" and "British Summer Time" there (and show with a jolly useful Converter.Utf16FromBytes() call!).

But I gather from skimming M$ web stuff that there should be a bias value in minutes in there somewhere, amounting to 60 minutes of daylight saving at the moment, but I can't find it...

Isn't this standard locale information that should be readily available? :confused:

Mike.
 

agraham

Expert
Licensed User
Isn't this standard locale information that should be readily available?
If you mean visible to the user then I don't think so, at least in Windows. I think the DST has always been either manual,as in the old days :), or automatic and invisible to the user in more modern times.
 

mjcoon

Well-Known Member
Licensed User
If you mean visible to the user then I don't think so, at least in Windows. I think the DST has always been either manual,as in the old days :), or automatic and invisible to the user in more modern times.
I've long thought that given the USA has several time zones and daylight saving, Windows time handling is rather clumsy. (I believe that when the clocks change, you'll see the times you wrote yesterday's files also appear to change by one hour!)

But if I click on the time in the system tray, the calendar that appears shows "Current time zone: GMT Daylight Time".

I've found the "Active Time Bias" in the registry bytes, at the end. Equals -60 right now. Retrieved by:

Converter.Int32FromBytes(zti(), 168)

Mike
 

mjcoon

Well-Known Member
Licensed User
Sorry gents,
There is an error in
mnuSetSystemDateTime_Click
which I have corrected as:

B4X:
Sub mnuSetSystemDateTime_Click
  If GPS.Status="A" Then
    Dim x, i
    x =DateParse(GPS2Time(GPS.UTCTime))   'addition of time zone must account for date change
    x = x - x Mod cTicksPerDay 
    x = x + TimeParse(GPS2Time(GPS.UTCTime)) + zt * cTicksPerHour
...
End Sub
I have finally worked out what alfcen meant by the 'addition of time zone must account for date change' comment. It's because the TimeParse() function rather strangely adds the time increment to the current date to generate the full ticks value.

But this complication can be avoided completely by using the convenient TmeAdd() function. Thus the date is parsed first, as above, then the time added to it.

The same function can be used again to add the local offset (which Microsoft likes to keep as the increment to go from local time to UTC) directly in minutes, so no division by 60 is needed either.

Using ByteConverter DLL (which it happens that my code already was) rather than BitWise DLL, makes the code for deriving the local offset much simpler too.

Mike.
 

agraham

Expert
Licensed User
It's because the TimeParse() function rather strangely adds the time increment to the current date to generate the full ticks value
Yes, it's an annoying quirk of the .NET DateTime Parse method that it adds the current date to the time when it parses a string if there is no date specified. I have no idea why someone thought that behaviour was a good idea :(.
 

Filippo

Expert
Licensed User
Hallo agraham,

@Filippo - how about hiding "SYSTEMTIME" by renaming it "_SYSTEMTIME"
I added the change.

and providing the sources for merging?
I can not, I know myself not using c# :(

Ciao,
Filippo
 

mjcoon

Well-Known Member
Licensed User
By way of restitution for my criticism of alfcen's code (which he invited us to shorten) and pay-back for all the assistance here, I offer my version of the crucial portion.

It assumes the presence of a multi-line textBox1 for display of disparate times, which is of course optional. Only if the time disparity is greater than one second does it invite the user to confirm alteration of system time. The user can prevaricate as long as desired without impacting the accuracy!

It uses ByteConverter DLL rather than BitWise DLL, which makes the code for deriving the local offset much simpler.

The original system time is a parameter so that it can be measured at the time that the GPS time is acquired, so that the time taken to perform parsing is not added in.

I don't know why the local time offset appears at registry value byte 168 in my PDA versus byte zero in alfcen's.

B4X:
'Requires Registry DLL (object reg), ByteConverter DLL and Filippo's SysTime DLL (object SysTime)

Sub CompareSystemTime(nowTicks, yearUTC, monthUTC, dayUTC, hourUTC, minuteUTC, secondUTC)
   moString = Format(monthUTC, "D2")
   dyString = Format(dayUTC, "D2")
   yrString = Format(yearUTC, "D4")
   DateFormat("yyyy-mm-dd")
   TimeFormat("HH:mm:ss")
   dateString = yrString & "-" & moString & "-" & dyString
   dateTicks = DateParse(dateString)
   timeUTCTicks = TimeAdd(dateTicks, hourUTC, minuteUTC, secondUTC)
   textBox1.Text = "Date&time (UTC)=" & CRLF & cTab & Date(timeUTCTicks) & "  " & Time(timeUTCTicks)
   minsOffset = - GetActiveTimeBias
   timeTicks = TimeAdd(timeUTCTicks, 0, minsOffset, 0)
   disparity = Int((timeTicks - nowTicks) / cTicksPerSecond + 0.5)
   If disparity = 1 Then
      unit = " second"
   Else
      unit = " seconds"
   End If
   textBox1.Text = textBox1.Text & CRLF & "Date&time (local)=" & CRLF & cTab & Date(timeTicks) & "  " & Time(timeTicks) & _
         CRLF & "System time =" & CRLF & cTab & Date(nowTicks) & "  " & Time(nowTicks) & _
         CRLF & "Time disparity = " & disparity & unit
   If Abs(disparity) > 1 Then
      If Msgbox("Disparity = " &    disparity & unit, "Adjust system time?", cMsgboxYesNo) = cYes Then
         adjustTime(disparity)
      End If
   End If
End Sub

Sub GetActiveTimeBias      'In minutes, to go from local to UTC (!)
  Dim m, i, b
  Reg.New1
  Reg.RootKey(Reg.rtLocalMachine)
  If cPPC = True Then
    zti()=Reg.GetValue("Time","TimeZoneInformation")
    m = Converter.Int32FromBytes(zti(), 168)
  Else
    m = Reg.GetValue("System\CurrentControlSet\Control\TimeZoneInformation","ActiveTimeBias")
  End If
  Return m   
End Sub

Sub adjustTime(seconds)
   TimeObj.New1
   timeNow = Now
   timeAdjusted = timeNow + seconds * cTicksPerSecond
   TimeObj.SetDate(DateMonth(timeAdjusted),DateDay(timeAdjusted),DateYear(timeAdjusted))    ' Tweak the current system date
   TimeObj.SetTime(TimeHour(timeAdjusted),TimeMinute(timeAdjusted),TimeSecond(timeAdjusted))    ' Tweak the current System time
End Sub
 

mjcoon

Well-Known Member
Licensed User
By way of restitution for my criticism of alfcen's code (which he invited us to shorten) and pay-back for all the assistance here, I offer my version of the crucial portion. ...
Back then, I complained that alfcen's code did not appear to allow for daylight saving (because at least in my registry it was not included in the data that he extracted).

I offered my own alternative, which seemed to work in zulu time zone and with daylight saving.

But now I try to re-visit the code I find that my registry content still thinks that we are in British Summer Time and daylight saving.

Has anyone in the interim found a reliable way of determining the offset between UTC and local time?

Mike.
 

agraham

Expert
Licensed User
Is this what you want. Obj1 is a Door library Object, Args1 is a Door library ObjectArray.
B4X:
   Obj1.New1(False)
   Args1.New1(1)
   Args1.SetValue(0, 0, "System.Int64")
   Obj1.CreateNew2("System.DateTime", Args1.Value)
   Obj1.Value = Obj1.GetProperty("UtcNow")
   UtcTicks = Obj1.GetProperty("Ticks")
   LocalOffset = Now - UtcTicks
 

nl1007

Member
Licensed User
Hi Filippo,

I think there is an error in your help file for SetDate

Its looking as if the Day and Month are swapped i.e. it should read:
Syntax: SetDate(Month As Integer, Day As Integer, Year As Integer) :)
I didn't notice a confirmation of this, but swapping them over does set the date..
Does anybody know why the US date format is so illogical? It causes so many problems.. (and partial implementation / use of 'regional settings', even within the same [MS] Application, just makes it worse)
 
Top