Come convertire ora Locale in ora UTC Delphi XE2? e come convertire di nuovo dall’UTC in ora locale?

Sto usando Delphi xe2 e sto cercando di memorizzare i record utilizzando UTC datetime nel mio database e poi ripristinarlo quando un client si legge nel suo locale datetime ? qualsiasi idea di come fare questo indietro indietro di conversione ?

InformationsquelleAutor Dreamer64 | 2013-03-22

 

4 Replies
  1. 18

    Questa è la funzione che uso per la conversione da UTC locali.

    function LocalDateTimeFromUTCDateTime(const UTCDateTime: TDateTime): TDateTime;
    var
      LocalSystemTime: TSystemTime;
      UTCSystemTime: TSystemTime;
      LocalFileTime: TFileTime;
      UTCFileTime: TFileTime;
    begin
      DateTimeToSystemTime(UTCDateTime, UTCSystemTime);
      SystemTimeToFileTime(UTCSystemTime, UTCFileTime);
      if FileTimeToLocalFileTime(UTCFileTime, LocalFileTime) 
      and FileTimeToSystemTime(LocalFileTime, LocalSystemTime) then begin
        Result := SystemTimeToDateTime(LocalSystemTime);
      end else begin
        Result := UTCDateTime;  // Default to UTC if any conversion function fails.
      end;
    end;

    Come si può vedere la funzione trasforma la data UTC ora come segue:

    • Data /ora -> sistema di tempo
    • Ora di sistema -> file tempo
    • Tempo del File -> file locale tempo (questa è la conversione da UTC locali)
    • Locale ora del file -> sistema di tempo
    • Ora di sistema -> data ora

    Dovrebbe essere ovvio come invertire questo.


    Di notare che questa conversione considera legale in quanto è ora piuttosto che come è/era al momento convertito. Il DateUtils.TTimeZone tipo, introdotto nel XE, tenta di fare proprio questo. Il codice diventa:

    LocalDateTime := TTimeZone.Local.ToLocalTime(UniversalDateTime);

    In un’altra direzione, utilizzare ToUniversalTime.

    Questa classe sembra essere (vagamente) modellata sull’ .net Fuso orario classe.

    Una parola di avvertimento. Non aspettatevi il tentativo per conto dell’ora solare /legale al momento di essere convertiti per essere accurato al 100%. È semplicemente impossibile ottenere che. Almeno senza una macchina del tempo. E questo solo considerando volte in futuro. Anche in passato sono complesse. Raymond Chen discute qui: Perché l’Ora legale è nonintuitive.

    • la conversione di dati storici locali dati in regioni con l’ora legale regioni hanno bisogno di una gestione speciale
    • Che dipende dalle esigenze.
    • Avere un parametro chiamato UTCDateTime, e una funzione chiamata UTCDateTime, entrambi con lo stesso tipo, mi fa male la testa. Credo che il suo utilizzo previsto è di usare o uno o l’altro, ma il modo in cui si presenta, lo fa apparire come LocalDateTimeFromUTCDateTime() vuole chiamare il UTCDateTime funzione, ma in realtà non è, perché utilizza il UTCDateTime parametro. Tipo di confusione.
    • Hai ragione. Ho rimosso il spurie fuorviante funzione. Sarò aver poppa parole con l’autore originale (nello specchio!)
    • Bello, in grado di aggiudicazione +1 ora.
    • +1 per TTimeZone.Local.ToLocalTime
    • Il codice non è corretto. Quando l’UTC unix tempo era 567302400, sul mio orologio era di 1:00 perché abbiamo avuto il tempo standard. Ma la funzione uscita 2:00 (come di questa scrittura, che abbiamo attualmente DST). Raymond Chen consiglia di utilizzare SystemTimeToTzSpecificLocalTimeEx invece di FileTimeToLocalFileTime ad esempio, perché rispetta l’ora legale dell’argomento invece di utilizzare l’ora legale corrente, che è importante conversione storico timestamp di una leggibile tempo. (vedi goo.gl/t94UNi ) Tuttavia, la soluzione utilizzando TTimeZone.Local.ToLocalTime è corretto.
    • Il codice è corretto che si fa quello che si intende fare. Se non soddisfa le vostre diverse esigenze che è un’altra questione.
    • Ok, forse ho una diversa aspettativa su ciò che questa funzione dovrebbe fare. Ma al di là di che, implicitamente detto nel tuo post che la funzione LocalDateTimeFromUTCDateTime è il complesso variante di TTimeZone.Local.ToLocalTime . Che non è vero quanto DateUtils.Local.ToLocalTime dà risultati diversi rispetto al tuo codice, se applicato ai valori storici. Si dovrebbe rendere chiaro nel post che entrambe le soluzioni hanno un comportamento differente. Quella non è la versione “semplificata” variante degli altri.
    • Fammi dare un’occhiata. Non credo semplificato/complicato è utile terminologia.
    • È meglio così?
    • Sì. Grazie.
    • Penso di Raimondo articoli su questo argomento mostra perché il conto per l’ora legale in base allo stato ora potrebbe essere a volte più desiderabile di approccio.

  2. 11

    è possibile utilizzare TzSpecificLocalTimeToSystemTime e funzione systemtimetotzspecificlocaltime da kernel32.

    var
      Form1: TForm1;
    
    function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation; var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall;
    function SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation: PTimeZoneInformation; var lpUniversalTime,lpLocalTime: TSystemTime): BOOL; stdcall;
    
    implementation
    
    function TzSpecificLocalTimeToSystemTime; external kernel32 name 'TzSpecificLocalTimeToSystemTime';
    function SystemTimeToTzSpecificLocalTime; external kernel32 name 'SystemTimeToTzSpecificLocalTime';
    
    {$R *.dfm}
    
    
    Function DateTime2UnivDateTime(d:TDateTime):TDateTime;
    var
     TZI:TTimeZoneInformation;
     LocalTime, UniversalTime:TSystemTime;
    begin
      GetTimeZoneInformation(tzi);
      DateTimeToSystemTime(d,LocalTime);
      TzSpecificLocalTimeToSystemTime(@tzi,LocalTime,UniversalTime);
      Result := SystemTimeToDateTime(UniversalTime);
    
    end;
    
    Function UnivDateTime2LocalDateTime(d:TDateTime):TDateTime;
    var
     TZI:TTimeZoneInformation;
     LocalTime, UniversalTime:TSystemTime;
    begin
      GetTimeZoneInformation(tzi);
      DateTimeToSystemTime(d,UniversalTime);
      SystemTimeToTzSpecificLocalTime(@tzi,UniversalTime,LocalTime);
      Result := SystemTimeToDateTime(LocalTime);
    end;
    
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
    
     Date,Univdate,DateAgain:TDateTime;
    
    begin
      Date := Now;
      Univdate := DateTime2UnivDateTime(Date);
      DateAgain := UnivDateTime2LocalDateTime(Univdate);
      Showmessage(DateTimeToStr(Date) +#13#10 + DateTimeToStr(Univdate)+#13#10 + DateTimeToStr(DateAgain));
    end;
    • Sapete se supporta la funzione systemtimetotzspecificlocaltime “storico” ora legale informazioni, come tzdb?
    • Il metodo di systemtimetotzspecificlocaltime funzione può calcolare l’ora locale in modo non corretto sotto le seguenti condizioni: Il fuso orario utilizza un diverso UTC offset per il vecchio e il nuovo anno. Il tempo UTC essere convertiti e calcolato che ora locale in diversi anni. msdn.microsoft.com/de-de/library/windows/desktop/…
    • C’è un piccolo errore nel codice di cui sopra. In UnivDateTime2LocalDateTime, la linea DateTimeToSystemTime(d,LocalTime); dovrebbe leggere DateTimeToSystemTime(d,UniversalTime);
    • grazie mille.
  3. 1

    Se il client utilizza un locale Delphi applicazione, questo può essere fatto con la data di Sistema funzioni.

    Tuttavia, se siete in un ambiente client/server (per esempio Delphi app è una web server e il client riceve solo le pagine HTML), è necessario convertire ora locale dell’utente in modo diverso. Il server deve sapere che il fuso orario dell’utente, e la conversione in modo appropriato.

    Anche l’ora legale può causare mal di testa, se l’applicazione ha bisogno di convertire i dati storici – è necessario conoscere se c’era l’ora legale in vigore per l’utente regione.

    In questi casi di utilizzo, il Fuso Orario Database per Delphi può essere utile.

    TZDB fornisce un semplice database e specializzata fuso orario classe che
    permette di accedere a tutti i fusi orari supportato dal Database dei fusi
    progetto.

    Non sapevo che c’è la funzione systemtimetotzspecificlocaltime ma basta leggere che Jon Skeet preferisce TZDB per il fuso orario di movimentazione.

Lascia un commento