You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
Hi! I'm trying to convert a UTC time to a Local Time Zone Time. I tried the SystemTimeToTzSpecificLocalTime Win32 api function, but I realized it doesn't work under Win95 or Win98. What is the best method for converting a UTC time to a Local Time Zone Time?
Thanks!
Scott
Scott Wolfington
[url="http://www.boogietools.com"]http://www.boogietools.com[/url]
Why doing that difficult?
PowerBasic for Windows/the Windows' API has local time aboard:
DECLARE SUB GetLocalTime LIB "KERNEL32.DLL" ALIAS "GetLocalTime" (lpSystemTime AS SYSTEMTIME)
------------------
[This message has been edited by Egbert Zijlema (edited April 09, 2000).]
Egbert Zijlema, journalist and programmer (zijlema at basicguru dot eu) http://zijlema.basicguru.eu *** Opinions expressed here are not necessarily untrue ***
I'm grabbing the UTC time from a NIST server on the Internet (time.nist.gov). I need to use the UTC time from the NIST server to set my local machine time.
Thanks for any help you can offer.
Scott
Scott Wolfington
[url="http://www.boogietools.com"]http://www.boogietools.com[/url]
Originally posted by Scott Wolfington: I'm grabbing the UTC time from a NIST server on the Internet (time.nist.gov). I need to use the UTC time from the NIST server to set my local machine time.
Thanks for any help you can offer.
Scott
Scott, I use this and it works fine.
Call UtcConvert with the UTC value and it will return formatted strings to you that take DST into account.
Ray
Code:
SUB UTCtoSystemTime(BYVAL t AS DWORD,st AS SYSTEMTIME)
LOCAL b AS BYTE PTR
LOCAL utc AS QUAD
LOCAL lt AS QUAD
utc=(t* 10000000) + 116444736000000000
FileTimeToLocalFileTime BYVAL VARPTR(utc), BYVAL VARPTR(lt)
FileTimeToSystemTime BYVAL VARPTR(lt), st
END SUB
FUNCTION utcConvert(BYVAL utc AS DWORD) AS STRING
LOCAL syst AS SYSTEMTIME
LOCAL dt$
LOCAL h$
UTCtoSystemTime utc, syst
dt$= FORMAT$(syst.wmonth,"##")+"/"+FORMAT$(syst.wday,"##")+"/"+FORMAT$(syst.wyear,"####")
REPLACE " " WITH "0" IN dt$
h$=FORMAT$(syst.whour,"##")+":"+FORMAT$(syst.wminute,"##")+":"+FORMAT$(syst.wsecond,"##")
REPLACE " " WITH "0" IN h$
FUNCTION = dt$+"/"+h$
END FUNCTION
How do I get the UTC time passed back from the time server into the dword format? The data that comes back from the server is a string, I parse it out, and then I put the values into a SYSTEMTIME Type variable.
Also, can you explain the utc=(t* 10000000) + 116444736000000000
line of code? I don't really know what that's doing. Thanks a lot!
Scott
------------------
Scott Wolfington
[url="http://www.boogietools.com"]http://www.boogietools.com[/url]
Oh yeah, this is how I'm currently trying to do it, but it doesn't seem to be working correctly.
-sTimeUTC is a SYSTEMTIME TYPE holding the UTC time information
-sTimeLocal is a SYSTEMTIME TYPE which should contain the local system time when these 3 lines of code are finished.
-fTimeUTC is a FILETIME TYPE
-fTimeLocal is a FILETIME TYPE
Result = SystemTimeToFileTime (sTimeUTC, fTimeUTC)
Result = FileTimeToLocalFileTime(fTimeUTC, fTimeLocal)
Result = FileTimeToSystemTime (fTimeLocal, sTimeLocal)
Scott --
look this sub.
It seems to me that ft like parameter in this sub is the same as fTimeUTC after Result = SystemTimeToFileTime (sTimeUTC, fTimeUTC)
Code:
Function FileDateTime(ft As FileTime) As String
Local st As SystemTime
Local zText As Asciiz * 255
Local Temp As String
' -- Convert the file time from UTC to local time
FileTimeToLocalFileTime ft, ft
' -- Convert the file time into a compatible system time
FileTimeToSystemTime ft, st
' -- Create a date string using the local settings
GetDateFormat %LOCALE_USER_DEFAULT, %DATE_SHORTDATE, st, ByVal %NULL, zText, 255
Temp = zText
' -- Create a time string using the local settings
GetTimeFormat %LOCALE_USER_DEFAULT, %TIME_NOSECONDS, st, ByVal %NULL, zText, 255
' -- Return the file date and time
Function = Temp + " " + zText
End Function
How do I get the UTC time passed back from the time server into the dword format? The data that comes back from the server is a string, I parse it out, and then I put the values into a SYSTEMTIME Type variable.
How are you getting it? I get it via NTP port 37 and use cvdwd to convert it to pass to the function.
Also, can you explain the utc=(t* 10000000) + 116444736000000000
line of code? I don't really know what that's doing. Thanks a lot!
That converts the time returned from NTP (UTC time) which has a base year of 1970 to a Windows time
which has a base somwhere around 1601 I think. It's stupid, but it works.
I use it to time sync all my NT systems.
Here, this works, in fact there are a few things you may need to be aware of depending what type of time you are dealing with.
NIST time needs to be parsed but there are a few things that are in there that are confusing, so I am going to post a WHOLE lotta code, use what you want..
'This code is directly out of my ccdate.dll, be happy to provide you a copy of it (Source included)..
Keep this function handy under NT, not sure it's required but if you DON'T use it, my experience has been that hte clock updates
AFTER the app ends (Strange)...
Code:
If IsTrue SetTimePrivilege Then
Result = SendMessage(%HWND_BROADCAST, %WM_TIMECHANGE, 0, 0)
Result = SetSystemTime(st)
End if
'-----------------------------------------------------------------------------------
Function CheckAtomicTime(lserv As String,wPort As Long,aTimeOut As Long,Delay As Double, st As SYSTEMTIME) Export As String
Local buffer As String
Local lpbuf As String
Local UTCTime As String
Local vbdate As Double
Dim Start As Dword
Dim Stopp As Dword
Dim QT As QuadFILETIME
lserv = Extract$(Ltrim$(lserv), Any " (")
'51468 99-10-17 05:12:27 15 0 0 888.6 UTC(NIST) *
'Record your starttime In milliseconds
Start = TimeGetTime()
Tcp Open Port wPort At lserv As #1 TIMEOUT aTimeOut
Do
Tcp Recv #1, 1600, buffer
lpbuf = lpbuf + buffer
Loop While Len(buffer)
Tcp Close #1
lpbuf = Trim$(lpbuf, $LF)
Replace $LF With $CRLF In lpbuf
UTCTime = Trim$(lpbuf, $LF)
Function = UTCTime
Delay = TimeGetTime - Delay
vbDate = StrToVbDate(Parse$(UTCTime, Any " ",2) + " " + Parse$(UTCTime, Any " ",3))
VariantTimeToSystemTime vbDate, st
Stopp = TimeGetTime()
'Convert your Atomic time into a SYSTEMTIME structure ST
'FILETIME returns 100's of NANOSECONDS so you have to adjust
'Delay To reflect this resulotion
Delay = (Stopp - Start)* 10000
'convert your Atomic time In ST To FileTime In QT
SystemTimeToFileTime ST,QT
'Now Add the delay To the Quad-element that overlay the FILETIME-struct
QT.qdTime = QT.qdTime + Delay
'Convert back To SYSTEMTIME
FileTimeToSystemTime QT,ST
Delay = Delay\10000
End Function
'-----------------------------------------------------------------------------------
Function RFC868Time()Export As Dword
Local VarTime As Double
Local st As SYSTEMTIME
Local hh&, mm&, ss&
GetSystemTime st 'GMT Time!
hh& = st.wHour * 3600
st.wHour = 0
mm& = st.wMinute * 60
st.wMinute = 0
ss& = st.wSecond
st.wSecond = 0
SystemTimeToVariantTime st,VarPtr(VarTime)
Function = (Int(VarTime)-2) * 86400 + HH& + MM& + SS&
End Function
'-----------------------------------------------------------------------------------
Sub RFC868toSystemTime(ByVal t As Dword, st As SYSTEMTIME) Export
'b = Return From Port 37 time server
'receive the time as a 32 bit binary number
'To use: RFC868toSystemTime CVDWD(b), st
Local b As Byte Ptr
Local utc As Quad
Local lt As Quad
' Gotta reverse the bytes for the internet
b = VarPtr(t)
Swap @b[0], @b[3]
Swap @b[1], @b[2]
utc = t
utc = (utc * 10000 * 1000) + (94354848 * 100000 * 10000)
FileTimeToLocalFileTime ByVal VarPtr(utc), ByVal VarPtr(lt)
FileTimeToSystemTime ByVal VarPtr(lt), st
End Sub
'-----------------------------------------------------------------------------------
'"Wed, 13 Oct 1999 15:07:52 -0700"
'The "-0700" is the offset From GMT (seven hours In this Case).
Function InetTime() Export As String
Local tz As TIME_ZONE_INFORMATION
Local d As Asciiz * 64
Local t As Asciiz * 64
Local z As String
GetDateFormat %LOCALE_USER_DEFAULT, %NULL, ByVal %NULL, "ddd',' d MMM yyyy", d, 64
GetTimeFormat %LOCALE_USER_DEFAULT, %NULL, ByVal %NULL, "HH':'mm':'ss", t, 64
GetTimeZoneInformation tz
If tz.bias < 0 Then
tz.bias = Abs(tz.bias)
z = ""
Else
z = "-"
End If
tz.bias = (tz.bias \ 60) * 100 + (tz.bias Mod 60)
z = z & Format$(tz.bias, "0000")
Function = d & " " & t & " " & z
End Function
'===================================<Time Conversion Functions to SYSTEMTIME>==================
Function uString(ByVal x As String)Export As String
Local y As String
Local n As Integer
If Len(x) Then
For n = 1 To Len(x)
y = y + Mki$(Asc(x, n))
Next n
End If
Function = y
End Function
'------------------------------------------------------------------------------
Function StrToVbDate(ByVal dt As String) Export As Double
Local x As Long
Local y As String
Local vbdate As Double
dt = uString(dt)
If IsFalse(VarDateFromStr(ByVal StrPtr(dt), 0, 0, vbdate)) Then
Function = vbdate
End If
End Function
'-----------------------------------------------------------------------------------
Function VbDateToStr(ByVal vbdate As Double) Export As String
Local d As Asciiz * 64
Local dt As String
Local st As SYSTEMTIME
Local tDay As Asciiz * 64
Local tTime As Asciiz * 64
VariantTimeToSystemTime vbdate, st
GetDateFormat %LOCALE_USER_DEFAULT,%DATE_SHORTDATE, st, ByVal %NULL, tDay, 64
GetTimeFormat %LOCALE_USER_DEFAULT, %TIME_FORCE24HOURFORMAT,st, ByVal %NULL, tTime, 64
Function = tDay + " " + tTime
End Function
'-----------------------------------------------------------------------------------
'Under NT you will need to adjust the time
Function SetTimePrivilege() Export As Long
Local hdlProcessHandle As Long
Local hToken As Long
Local tmpLuid As LUID
Local tp As TOKEN_PRIVILEGES
Local tpNewButIgnored As TOKEN_PRIVILEGES
Local BufferLength As Long
Local lBufferNeeded As Long
%TOKEN_ADJUST_PRIVILEGES = &H20
%TOKEN_QUERY = &H8
%SE_PRIVILEGE_ENABLED = &H2
hdlProcessHandle = GetCurrentProcess()
OpenProcessToken hdlProcessHandle, (%TOKEN_ADJUST_PRIVILEGES Or %TOKEN_QUERY), hToken
' Get the LUID for setSystemTime privilege.
LookupPrivilegeValue "", "SeSystemtimePrivilege",tmpLuid
tp.PrivilegeCount = 1
' One privilege to set
tp.Privileges(1).pLuid = tmpLuid
tp.Privileges(1).Attributes=%SE_PRIVILEGE_ENABLED
' Enable the SetSystemTime privilege in the access token of this process.
BufferLength = SizeOf(tpNewButIgnored)
Function= AdjustTokenPrivileges( ByVal hToken,ByVal 0,tp,ByVal BufferLength ,tpNewButIgnored,lBufferNeeded)
End Function
'-----------------
Scott Turchin
MCSE, MCP+I http://www.tngbbs.com
---------------------- True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi
The NIST Time Standard (I read the entire thing through, BORING!) has a comment about this:
'51468 99-10-17 05:12:27 15 0 0 888.6 UTC(NIST) *
So it breaks down like this (Doing from memory)
51468 - Modified Julian Date (I have the source if interested)
99-10-17 'Date I last worked on my Nuclear TimeServer (It's graphical and comical and works nice)..
05:12:27 - I wake up too early
15 0 0 - Number of days until next daylight savings time changover (??) and the 0 0 are used as a countdown when it is below 55 days I believe and then when it it past daylight savings time changeover day.....(I will have to find that doc again)...
888.6 milliseconds (Use with Network delay ot calculate to within 1 second)...
Scott Turchin
MCSE, MCP+I http://www.tngbbs.com
---------------------- True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi
Thanks for all of your help on this. I ended up not having to do all of these conversions after all. Here's what I did...
Get UTC time from time.nist.gov, parse out the return value to get Month, Day, Year, Hours, Minutes, Seconds, Milliseconds, create a SYSTEMTIME type variable and put all of these values into it, and then call the Windows api call "setSystemTime" with my SYSTEMTIME Type variable as it's parameter. It worked like a charm.
The reason my initial code didn't work was because I was passing in a two digit year value to the SystemTimeToFileTime function. I passed in a 4 digit year and it worked. I'm not using this anymore either though, just setSystemTime.
Does anyone see any problems with this method? Now, I just need to take a look at Scott T's code to take the "Network response time" into consideration when querying time.nist.gov.
Thanks again!
Scott
Scott Wolfington
[url="http://www.boogietools.com"]http://www.boogietools.com[/url]
This is a pretty good webpage that describes the different time formats... I see that the milliseconds value is "the number of milliseconds that NIST advances the time code to partially compensate for network delays." http://www.bldrdoc.gov/timefreq/service/nts.htm
Scott
------------------
Scott Wolfington
[url="http://www.boogietools.com"]http://www.boogietools.com[/url]
I'd be happy to supply you with my entire source if you are interested, it works, some of my issues that remain are simply what happens when I don't get a return, and I think I have a handle on most of that...
email me if interested mailto:[email protected][email protected]</A>
Also that link above, VERY good, that's the page I used when I wrote a function to send OUT the NIST time (I have to work on the daylight savings time)...
I just learned this:
msADV displays the number of milliseconds that NIST advances the time code to partially compensate for network delays. The advance is currently set to 50.0 milliseconds.
H is a health digit that indicates the health of the server. If H=0, the server is healthly. If H=1, then the server is operating properly but its time may be in error by up to 5 seconds. This state should change to fully healthy within 10 minutes. If H=2, then the server is operating properly but its time is known to be wrong by more than 5 seconds. If H=3, then a hardware or software failure has occurred and the amount of the time error is unknown.
[This message has been edited by Scott Turchin (edited April 08, 2000).]
Scott Turchin
MCSE, MCP+I http://www.tngbbs.com
---------------------- True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi
> UTC(NIST) * 'Indicates NIST standard time server.
When you connect to the NIST via a direct modem connection (as opposed to going through the internet) when your program receives the star character you can optionally echo it back. The NIST computer then measures the round-trip delay (from the time it sent the star to the time it gets it back), divides the delay by two, and sends the next string a fraction of a second early to compenstate for the phone-system delay. Does the internet-based system provide this functionality?
I Just reread that page.
NIST time is actually considered the Daytime Protocol (RFC-867)...
My impression from below would indicate that it does not matter whether it is internet, network-intranet, or dial up, when it receives the request for time, that time is sent back...when it was received. Ie the timestamp begins from the time the request is received, not anticipated etc...thhe * indicates it is On Time, or that's the On Time Marker from when the request was received, hence the client can then determine the network delay and do the math to calculate the difference...
Makes sense, the server says I am sending this stamp out NOW. and that marker is there, client gets it and determines it took 35 seconds to get it back, does the math (Hence my former posts about subtracting SYSTEMTIME's for network delay)....anyway, my opinion and impression is that it's up to the client...
The NIST states:
OTM (on-time marker) is an asterisk (*). The time values sent by the time code refer to the arrival time of the OTM. In other words, if the time code says it is 12:45:45, this means it is 12:45:45 when the OTM arrives.
[This message has been edited by Scott Turchin (edited April 08, 2000).]
Scott Turchin
MCSE, MCP+I http://www.tngbbs.com
---------------------- True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi
JJJJJ YR-MO-DA HH:MM:SS TT L H msADV UTC(NIST) OTM
Now I'm sorta baffled.....
Reading by this I would THINK like this:
Measure start request time.
Receive time back.
Measure stop time.
TempTime = Stop - Start
That should give you a TOTAL network delay...
But if the milliseconds is already adjusted then you have no basis to make a network delay assumption from BECAUSE your PC clock could be 3 minutes off, so you receive the request back from NIST with an adjustment so you ASSUME that they covered HALF of the network delay and you ASSUME that the return trip matches the request trip, and in fact it may NOT....So you record request time and receive time, divide by two? Another assumption...
This is designed to be within milliseconds, I will settle for .5 seconds but you've brought up a good point...
How do you measure network delay???
msADV displays the number of milliseconds that NIST advances the time code to partially compensate for network delays. The advance is currently set to 50.0 milliseconds.
OTM (on-time marker) is an asterisk (*). The time values sent by the time code refer to the arrival time of the OTM. In other words, if the time code says it is 12:45:45, this means it is 12:45:45 when the OTM arrives.
Scott Turchin
MCSE, MCP+I http://www.tngbbs.com
---------------------- True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.
Comment