Announcement

Collapse
No announcement yet.

Convert UTC time to Local Time Zone Time?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Convert UTC time to Local Time Zone Time?

    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]

  • #2
    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 ***

    Comment


    • #3
      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]

      Comment


      • #4
        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

        Comment


        • #5
          Hi Raymond!

          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]

          Comment


          • #6
            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)


            MSGBOX "Hour: " & STR$(sTimeLocal.wHour) & "--" & STR$(sTimeLocal.wMinute)

            The value I end up with for sTimeLocal.wHour is 1186.
            The value I end up with for sTimeLocal.wMinute is 2.



            ------------------
            Scott Wolfington
            [url="http://www.boogietools.com"]http://www.boogietools.com[/url]

            Comment


            • #7
              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
              ------------------

              Comment


              • #8

                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.

                Ray


                Comment


                • #9
                  Raymond,

                  Here's the function I'm using to bring it back
                  from time.nist.gov. This function was taken from
                  a post in the source code forum.

                  Scott

                  FUNCTION CheckAtomicTime() AS STRING

                  LOCAL buffer AS STRING
                  LOCAL lpbuf AS STRING
                  LOCAL lserv AS STRING


                  lserv = "time.nist.gov"

                  TCP OPEN PORT 13 AT lserv AS #1 TIMEOUT 30
                  IF ERR THEN
                  FUNCTION = ""
                  ELSE
                  DO
                  TCP RECV #1, 32767, buffer
                  lpbuf = lpbuf + buffer
                  LOOP WHILE LEN(buffer)

                  lpbuf = TRIM$(lpbuf, $LF)
                  TCP CLOSE #1
                  REPLACE $LF WITH $CRLF IN lpbuf
                  FUNCTION = lpbuf
                  END IF

                  END FUNCTION

                  ------------------
                  Scott Wolfington
                  [url="http://www.boogietools.com"]http://www.boogietools.com[/url]

                  Comment


                  • #10
                    Whoa that code looks familiar! *Grin*

                    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
                    mailto:[email protected][email protected]</A>
                    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

                    Comment


                    • #11
                      One more thing...(I love this stuff)..

                      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)...

                      UTC(NIST) * 'Indicates NIST standard time server.


                      Scott


                      ------------------
                      Scott
                      mailto:[email protected][email protected]</A>
                      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

                      Comment


                      • #12
                        Hi everyone,

                        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]

                        Comment


                        • #13
                          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]

                          Comment


                          • #14
                            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.


                            Scott


                            ------------------
                            Scott
                            mailto:[email protected][email protected]</A>

                            [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

                            Comment


                            • #15
                              Scott T. --

                              > 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?

                              -- Eric

                              ------------------
                              Perfect Sync: Perfect Sync Development Tools
                              Email: mailto:[email protected][email protected]</A>

                              "Not my circus, not my monkeys."

                              Comment


                              • #16
                                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.
                                ------------------
                                Scott
                                mailto:[email protected][email protected]</A>

                                [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

                                Comment


                                • #17
                                  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
                                  mailto:[email protected][email protected]</A>
                                  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

                                  Comment

                                  Working...
                                  X