Get the current date and time by internet in desktop application

Asked

Viewed 7,696 times

12

I am implementing a system lock by date, and I need to get the current date of Brasilia for example, which would be the official time of Brazil, or the date in time zone -3.

I believe that there are web services that do this and that are reliable, or maybe even the government provides this kind of service.

But I couldn’t find anything that would serve me effectively. So I’m coming to you.

Note: This is a Desktop application and I cannot trust the date of the running machine or database server.

  • The US government maintains the NIST - National Institute of Standards and Technology. It has several servers that inform, among other things, the current time, UTC. Hence just apply the Fuse or whatever you want. Here is the list of servers. If anyone wants to elaborate on that in a reply, feel free.

  • 5

    @Brazil has ntp.br, more reliable for those who are here due to low latency.

  • 1

    @bigown and Bacco, I did not mention the question because it will be necessary to implement it in 2 languages, Delphi 7 and C#.

  • Half of the question was answered, the date part was missing. ?

  • @Márcio you came to test the answers?

2 answers

12

Solution in C#

Original: https://stackoverflow.com/a/12150289/916193

public static DateTime GetNetworkTime()
{
    //Servidor nacional para melhor latência
    const string ntpServer = "a.ntp.br";

    // Tamanho da mensagem NTP - 16 bytes (RFC 2030)
    var ntpData = new byte[48];

    //Indicador de Leap (ver RFC), Versão e Modo
    ntpData[0] = 0x1B; //LI = 0 (sem warnings), VN = 3 (IPv4 apenas), Mode = 3 (modo cliente)

    var addresses = Dns.GetHostEntry(ntpServer).AddressList;

    //123 é a porta padrão do NTP
    var ipEndPoint = new IPEndPoint(addresses[0], 123);
    //NTP usa UDP
    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

    socket.Connect(ipEndPoint);

    //Caso NTP esteja bloqueado, ao menos nao trava o app
    socket.ReceiveTimeout = 3000;     

    socket.Send(ntpData);
    socket.Receive(ntpData);
    socket.Close();

    //Offset para chegar no campo "Transmit Timestamp" (que é
    //o do momento da saída do servidor, em formato 64-bit timestamp
    const byte serverReplyTime = 40;

    //Pegando os segundos
    ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);

    //e a fração de segundos
    ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);

    //Passando de big-endian pra little-endian
    intPart = SwapEndianness(intPart);
    fractPart = SwapEndianness(fractPart);

    var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);

    //Tempo em **UTC**
    var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);

    return networkDateTime.ToLocalTime();
}

// stackoverflow.com/a/3294698/162671
static uint SwapEndianness(ulong x)
{
    return (uint) (((x & 0x000000ff) << 24) +
                   ((x & 0x0000ff00) << 8) +
                   ((x & 0x00ff0000) >> 8) +
                   ((x & 0xff000000) >> 24));
}

6


Delphi

In Delphi if you have installed the components of Indy(in recent versions of Delphi the Indy comes already embedded), you can get the time by using the component IdSntp.

Example:

{
   Na seção "Uses" coloque as units:
    IdComponent, IdTCPConnection, IdTCPClient, IdSNTP,
    IdBaseComponent, IdUDPClient, IdUDPBase
}
Function ReturnTimeInternet(const Servidor: string): string;
Var
SNTP: TIdSNTP;
begin
SNTP := TIdSNTP.Create(nil);
try
 SNTP.Host := Servidor;
 Result := TimeToStr(SNTP.DateTime);
finally
 SNTP.Disconnect;
 SNTP.Free;
end;
end;

Example of use:

procedure TForm1.Button1Click(Sender: TObject);
Var
Tempstr: string;
begin
Tempstr := ReturnTimeInternet('pool.ntp.br'); // Ou um servidor de sua preferência
showmessage(format('O horário atual é %s.',[tempstr]));
end;

Browser other questions tagged

You are not signed in. Login or sign up in order to post.