2011-07-11 72 views
17

我可以德爾福TDate轉換爲ISO 8601格式很容易使用這個:如何將ISO 8601字符串轉換爲Delphi TDate?

DateTimeToString(result, 'yyyy-mm-dd', myDate); 

什麼是慣用的方式做逆轉換? StringToDateTime()似乎不存在。

很明顯,我可以通過手動解析字符串並對結果進行編碼來實現「硬」的方式,但這似乎是一個糟糕的選擇。

+0

可能重複(http://stackoverflow.com/questions/3786823/converting-a-string-to-tdatetime-based-on-任意格式) – NGLN

回答

15

爲什麼重新發明輪子?

XML使用ISO 8601進行日期和日期時間存儲。

德爾福已經在XSBuiltIns單位德爾福6自內置的支持。

This answer explains how的日期時間,這是隻能使用TXSDate類Date:

with TXSDate.Create() do 
    try 
    AsDate := Date; // convert from TDateTime 
    DateString := NativeToXS; // convert to WideString 
    finally 
    Free; 
    end; 

with TXSDate.Create() do 
    try 
    XSToNative(DateString); // convert from WideString 
    Date := AsDate; // convert to TDateTime 
    finally 
    Free; 
    end; 
7

我認爲這應該工作...文檔說這些方法的重載版本是用於線程,但它可以很方便地指定您希望在當時使用的格式設置。

Function ISO8601ToDateTime(Value: String):TDateTime; 
var 
    FormatSettings: TFormatSettings; 
begin 
    GetLocaleFormatSettings(GetThreadLocale, FormatSettings); 
    FormatSettings.DateSeparator := '-'; 
    FormatSettings.ShortDateFormat := 'yyyy-MM-dd'; 
    Result := StrToDate(Value, FormatSettings); 
end; 

可以的這門課程的寫入變種StrToDateDef和TryStrToDate具有同等功能

+3

您也可能想要初始化格式設置,並使用系統默認值。取決於您是否將它用於除解析日期外的其他內容: 'GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT,FormatSettings);'用系統默認值填充FormatSettings記錄。 –

+0

@羅爾德,謝謝..我正在運行一些測試!我會稍後更新 –

+2

絕對使用「線程安全」重載版本,否則,如果您使用DateToStr或FormatDateTime與'c'或'ddddd'或其他任何使用方式,您將更改應用程序顯示日期的方式ShortDateFormat。 –

7

你可以在我們的SynCommons unit異-8601轉換例程。

它已經對速度進行了深度優化,所以它比DateTimeToString()函數等要快得多,但當然代碼更難以遵循。 )

procedure Iso8601ToDateTimePUTF8CharVar(P: PUTF8Char; L: integer; var result: TDateTime); 
var i: integer; 
    B: cardinal; 
    Y,M,D, H,MI,SS: cardinal; 
// we expect 'YYYYMMDDThhmmss' format but we handle also 'YYYY-MM-DD hh:mm:ss' 
begin 
    result := 0; 
    if P=nil then 
    exit; 
    if L=0 then 
    L := StrLen(P); 
    if L<4 then 
    exit; // we need 'YYYY' at least 
    if P[0]='T' then 
    dec(P,8) else begin 
    B := ConvertHexToBin[ord(P[0])]; // first digit 
    if B>9 then exit else Y := B; // fast check '0'..'9' 
    for i := 1 to 3 do begin 
     B := ConvertHexToBin[ord(P[i])]; // 3 other digits 
     if B>9 then exit else Y := Y*10+B; 
    end; 
    if P[4] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD 
    D := 1; 
    if L>=6 then begin // YYYYMM 
     M := ord(P[4])*10+ord(P[5])-(48+480); 
     if (M=0) or (M>12) then exit; 
     if P[6] in ['-','/'] then begin inc(P); dec(L); end; // allow YYYY-MM-DD 
     if L>=8 then begin // YYYYMMDD 
     D := ord(P[6])*10+ord(P[7])-(48+480); 
     if (D=0) or (D>MonthDays[true][M]) then exit; // worse is leap year=true 
     end; 
    end else 
     M := 1; 
    if M>2 then // inlined EncodeDate(Y,M,D) 
     dec(M,3) else 
    if M>0 then begin 
     inc(M,9); 
     dec(Y); 
    end; 
    with Div100(Y) do 
     result := (146097*YDiv100) shr 2 + (1461*YMod100) shr 2 + 
      (153*M+2) div 5+D-693900; 
    if (L<15) or not(P[8] in [' ','T']) then 
     exit; 
    end; 
    H := ord(P[9])*10+ord(P[10])-(48+480); 
    if P[11]=':' then inc(P); // allow hh:mm:ss 
    MI := ord(P[11])*10+ord(P[12])-(48+480); 
    if P[13]=':' then inc(P); // allow hh:mm:ss 
    SS := ord(P[13])*10+ord(P[14])-(48+480); 
    if (H<24) and (MI<60) and (SS<60) then // inlined EncodeTime() 
    result := result + (H * (MinsPerHour * SecsPerMin * MSecsPerSec) + 
      MI * (SecsPerMin * MSecsPerSec) + SS * MSecsPerSec)/MSecsPerDay; 
end; 

這是能夠處理來自UTF-8編碼緩衝器非常快的轉換成TDateTime。對於所有常量依賴關係,請檢查單元源代碼。

+0

典型。無論如何,我使用突觸,但從未意識到這包括:-) – Roddy

+4

雖然此功能不完全符合ISO8601。該規範說在日期和時間字符串之間使用「T」作爲分隔符。只有經雙方同意纔可以省略。其次,在字符串末尾不支持時區指示,這是許多Web服務所要求的。 –

6

更多的靈活性,你可以考慮Marco van de Voortscandate routine它處理你的字符串中的任何格式:

var 
    D: TDateTime; 
begin 
    D := ScanDate('yyyy-mm-dd', '2011-07-11'); 

final version(7KB .zip文件)的加入到FPC。

+2

英國權威並不等於荷蘭「definitief」。在這種情況下,荷蘭的「definitieve versie」被更好地翻譯爲「最終版本」。 「最終版本」更像是說「終極版」...然後,也許你打算說:-)) –

+0

@Marjan dankje ...;) – NGLN

+0

總是樂意幫助一個國家(窩)人 –

1
USES Soap.XSBuiltIns; 
... 
Function XMLDateTimeToLocalDateTime(const Value: String): TDateTime; 
begin 
    with TXSDateTime.Create do 
    try 
    XSToNative(Value); 
    result := AsDateTime; 
    finally 
    Free; 
    end; 
end; 

德爾福XE3

相關問題