NTP_GetTime

Share your advanced PureBasic knowledge/code with the community.
dige
Addict
Addict
Posts: 1404
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

NTP_GetTime

Post by dige »

Hi guys,

I actually only needed a time server query, because a computer here keeps forgetting its time due to an empty bios battery ;-) . ChatGPT delivered right away and even built the UI for it. Worked out of the box. Maybe someone can still use it

Code: Select all

; Credits: ChatGPT o4, Prompt by Dige

EnableExplicit

Structure NTPResult
  unixTime.q
  milliseconds.w
EndStructure

;--- Swap Endianness for long values
Procedure SwapEndianLong(val.l)
  ProcedureReturn ((val & $FF) << 24) | ((val & $FF00) << 8) | ((val & $FF0000) >> 8) | ((val & $FF000000) >> 24)
EndProcedure

;--- Calculate local time offset (e.g. +3600 for CET)
Procedure.q GetLocalTimeOffset()
  Protected local = Date()
  Protected st.SYSTEMTIME, ft.FILETIME, utc.q

  st\wYear   = Year(local)
  st\wMonth  = Month(local)
  st\wDay    = Day(local)
  st\wHour   = Hour(local)
  st\wMinute = Minute(local)
  st\wSecond = Second(local)

  SystemTimeToFileTime_(@st, @ft)
  LocalFileTimeToFileTime_(@ft, @ft)
  FileTimeToSystemTime_(@ft, @st)

  utc = Date(st\wYear, st\wMonth, st\wDay, st\wHour, st\wMinute, st\wSecond)

  ProcedureReturn local - utc
EndProcedure

;--- High-precision NTP time request
Procedure NTP_GetTime(*res.NTPResult, server.s = "ptbtime1.ptb.de")
  Protected ntpPacket.s = Space(48)
  PokeB(@ntpPacket, 27)

  Protected udp = OpenNetworkConnection(server, 123, #PB_Network_UDP)
  If udp = 0 : ProcedureReturn #False : EndIf

  SendNetworkData(udp, @ntpPacket, 48)

  Protected Timeout = ElapsedMilliseconds() + 3000
  Protected *mem = AllocateMemory(48)
  If *mem = 0 : CloseNetworkConnection(udp) : ProcedureReturn #False : EndIf

  Repeat
    If NetworkClientEvent(udp) = #PB_NetworkEvent_Data
      ReceiveNetworkData(udp, *mem, 48)

      Protected rawSec.l  = PeekL(*mem + 40)
      Protected rawFrac.l = PeekL(*mem + 44)

      Protected seconds.q = SwapEndianLong(rawSec)
      Protected fraction.q = SwapEndianLong(rawFrac)

      *res\unixTime = seconds - 2208988800
      *res\milliseconds = (fraction * 1000) / $100000000

      FreeMemory(*mem)
      CloseNetworkConnection(udp)
      ProcedureReturn #True
    EndIf
    Delay(10)
  Until ElapsedMilliseconds() > Timeout

  FreeMemory(*mem)
  CloseNetworkConnection(udp)
  ProcedureReturn #False
EndProcedure

;--- Set system time (UTC, Windows only)
Procedure SetSystemTimeFromUnix(unixTime.q)
  Protected st.SYSTEMTIME

  st\wYear   = Year(unixTime)
  st\wMonth  = Month(unixTime)
  st\wDay    = Day(unixTime)
  st\wHour   = Hour(unixTime)
  st\wMinute = Minute(unixTime)
  st\wSecond = Second(unixTime)
  st\wMilliseconds = 0

  SetSystemTime_(@st)
EndProcedure

;--- GUI setup
Procedure InitGUI()
  OpenWindow(0, 0, 0, 620, 400, "NTP Time Sync", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget(0, 20, 15, 580, 20, "Last Sync:")
  ListIconGadget(1, 20, 40, 580, 260, "Timestamp", 180, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
  AddGadgetColumn(1, 1, "Offset (ms)", 120)
  AddGadgetColumn(1, 2, "NTP Time", 140)
  AddGadgetColumn(1, 3, "System Time", 140)
  ButtonGadget(2, 20, 320, 200, 30, "Set System Time (UTC)")
  ButtonGadget(3, 240, 320, 180, 30, "Sync Now")
  ButtonGadget(4, 440, 320, 160, 30, "Toggle Auto-Refresh")
  TextGadget(5, 20, 360, 580, 20, "Status:")
EndProcedure

;--- Time difference logging
Procedure LogTimeDiff()
  Static ntp.NTPResult
  Protected sysTime.q = Date()
  Protected result.s
  Protected localOffset = GetLocalTimeOffset()

  If NTP_GetTime(@ntp)
    ; Adjust system time to UTC
    Protected sysUTC.q = sysTime - localOffset
    Protected ntpTotalMS.q = ntp\unixTime * 1000 + ntp\milliseconds
    Protected sysTotalMS.q = sysUTC * 1000
    Protected deltaMS.q = ntpTotalMS - sysTotalMS

    ; Local view for GUI
    Protected ntpLocalTime.q = ntp\unixTime + localOffset

    result = FormatDate("%yyyy-%mm-%dd %hh:%ii:%ss", Date())
    AddGadgetItem(1, -1, result + Chr(10) + Str(deltaMS) + Chr(10) +
                  FormatDate("%hh:%ii:%ss", ntpLocalTime) + "." + RSet(Str(ntp\milliseconds), 3, "0") + Chr(10) +
                  FormatDate("%hh:%ii:%ss", sysTime))

    SetGadgetText(0, "Last Sync: " + FormatDate("%hh:%ii:%ss", Date()))
    SetGadgetText(5, "NTP response OK (" + Str(deltaMS) + " ms offset)")
  Else
    SetGadgetText(5, "⚠ Error: no response from NTP server")
  EndIf
EndProcedure

;--- Main
InitGUI()

Define autoRefresh = #True, ntp.NTPResult
AddWindowTimer(0, 1, 5000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break

    Case #PB_Event_Timer
      If EventTimer() = 1 And autoRefresh
        LogTimeDiff()
      EndIf

    Case #PB_Event_Gadget
      Select EventGadget()
        Case 2
          If NTP_GetTime(@ntp)
            SetSystemTimeFromUnix(ntp\unixTime)
            SetGadgetText(5, "System time set (UTC)")
          Else
            SetGadgetText(5, "⚠ Failed to set system time")
          EndIf

        Case 3
          LogTimeDiff()

        Case 4
          autoRefresh ! 1
          If autoRefresh
            SetGadgetText(5, "Auto-refresh enabled")
          Else
            SetGadgetText(5, "Auto-refresh disabled")
          EndIf
      EndSelect
  EndSelect
ForEver


"Daddy, I'll run faster, then it is not so far..."
Fred
Administrator
Administrator
Posts: 18199
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: NTP_GetTime

Post by Fred »

Could you post your prompt ?
infratec
Always Here
Always Here
Posts: 7613
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: NTP_GetTime

Post by infratec »

Also before ChatGpt it was possible to get ntp time :wink:

https://www.purebasic.fr/english/viewtopic.php?p=508216
User avatar
Caronte3D
Addict
Addict
Posts: 1361
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: NTP_GetTime

Post by Caronte3D »

Someone with experience in AI should train a model using this entire forum. It would be amazing.
Quin
Addict
Addict
Posts: 1132
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: NTP_GetTime

Post by Quin »

Caronte3D wrote: Mon Mar 24, 2025 8:46 pm Someone with experience in AI should train a model using this entire forum. It would be amazing.
+1, as long as they do it without putting 4k+ users online at once :D
An on-machine AI model to ask about PureBasic in the IDE itself could be really cool.
User avatar
mk-soft
Always Here
Always Here
Posts: 6242
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: NTP_GetTime

Post by mk-soft »

It's scary how far AI has already come ...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
infratec
Always Here
Always Here
Posts: 7613
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: NTP_GetTime

Post by infratec »

And ChatGPT still don't know that Space(48) occupies 98 bytes and not 48.

Maybe the AI was trained with a very old PB version in Ascii mode :mrgreen:
Quin
Addict
Addict
Posts: 1132
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: NTP_GetTime

Post by Quin »

infratec wrote: Mon Mar 24, 2025 10:35 pm And ChatGPT still don't know that Space(48) occupies 98 bytes and not 48.

Maybe the AI was trained with a very old PB version in Ascii mode :mrgreen:
Nope, it's just an AI and doesn't actually know anything about what it's talking about, I could ask it a hundred times and half the time it would probably tell me 98 :mrgreen:
dige
Addict
Addict
Posts: 1404
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: NTP_GetTime

Post by dige »

Fred wrote: Mon Mar 24, 2025 8:25 pm Could you post your prompt ?
Hi Fred, I just started with: “Create a complete PureBasic code that retrieves the current time from an NTP server like ptbtime1.ptb.de.”
ChatGPT then offered me further code improvements, which I confirmed. Like conversion to 64 bit, GUI, conversion from UTC to local time.

Kind regards

Dige
"Daddy, I'll run faster, then it is not so far..."
Post Reply