procedimientos para hora funciones funcion fecha xml delphi

xml - para - funciones en delphi



En Delphi hay una funciĆ³n para convertir la fecha y hora de XML a TDateTime (3)

Delphi tiene una unidad XSBuiltIns (desde Delphi 6) que contiene tipos de datos que pueden ayudarlo a convertir algunos tipos de datos XML:

(hay más, como TXSDecimal , tienes la idea)

Todos estos contienen al menos estos dos métodos:

Puedes usarlo así:

with TXSDateTime.Create() do try AsDateTime := ClientDataSetParam.AsDateTime; // convert from TDateTime Attribute.DateTimeValue := NativeToXS; // convert to WideString finally Free; end; with TXSDateTime.Create() do try XSToNative(XmlAttribute.DateTimeValue); // convert from WideString CurrentField.AsDateTime := AsDateTime; // convert to TDateTime finally Free; end;

Eso te ayudara a llegar.

--jeroen

La fecha y hora XML están en el formato

''-''? yyyy ''-'' mm ''-'' dd ''T'' hh '':'' mm '':'' ss (''.'' s +)? (zzzzzz)?

fueron

• ''-''? aaaa es un número de cuatro o más dígitos opcionalmente con signo negativo que representa el año; si hay más de cuatro dígitos, los ceros a la izquierda están prohibidos, y está prohibido "0000"

• los '''' restantes son separadores entre partes de la porción de fecha;

• el primer mm es un número de dos dígitos que representa el mes;

• dd es un número de dos dígitos que representa el día;

• ''T'' es un separador que indica que la hora del día sigue;

• hh es un número de dos dígitos que representa la hora; ''24'' está permitido si los minutos y segundos representados son cero, y el valor dateTime así representado es el primer instante del día siguiente (la propiedad hora de un objeto dateTime en el · espacio de valor · no puede tener un valor mayor a 23) ;

• '':'' es un separador entre partes de la porción del tiempo del día;

• el segundo mm es un número de dos dígitos que representa el minuto;

• ss es un número de dos dígitos enteros que representa los segundos completos;

• ''.'' s + (si está presente) representa los segundos fraccionarios;

• zzzzzz (si está presente) representa la zona horaria (como se describe a continuación).

aquí hay más ejemplos

Ejemplo simple 2009-08-31T19: 30: 00

Ejemplos más complejos

2002-10-10T12: 00: 00-05: 00 (mediodía del 10 de octubre de 2002, horario de verano central y hora estándar del este de EE. UU.) Es 2002-10-10T17: 00: 00Z , cinco horas después de 2002 -10-10T12: 00: 00Z .

ver www.w3.org/TR/2004/REC-xmlschema-2-20041028/datatypes.html para más información


Esto ya ha sido respondido bien, pero agregaré aquí algunas cosas que terminé haciendo en un caso similar que tuve. De la unidad XSBuiltIns encontré el método

function XMLTimeToDateTime(const XMLDateTime: InvString; AsUTCTime: Boolean = False): TDateTime;

que parecía ser lo que yo quería. Lo que quería era poder analizar todas las diferentes cadenas de tiempo XML definidas aquí: w3schools.com/schema/schema_dtypes_date.asp

Esto incluye cadenas con solo Fecha, solo Hora o Fecha y Hora, y todas estas con las opciones de zona horaria especificada o hora UTC o local para la cadena de origen, y el valor de retorno como hora local. Además, cuando se le da solo un tiempo, quería que siempre estuviera dentro del "día cero", es decir, después de la operación, la parte completa del TDateTime devuelto (emitida a número real) era cero.

Finalmente, quería que la función devuelva DateTime.MinValue en entrada errónea (principalmente cuando se le da una cadena vacía).

No estoy seguro de si estaba usando la función de forma diferente a como está especificada, pero al menos desafortunadamente falló en varios lugares para mí. Terminé haciendo mi propia función alrededor de esta, que cubría todos los casos que encontré y ahora estoy bien en el futuro. Se puede argumentar que quizás hubiera sido mejor escribir todo el análisis yo mismo, ya que no podría haber sido mucho más complejo que la solución de problemas que terminé haciendo, pero al menos por el momento , Voy con lo que tengo y decidí publicarlo aquí también en caso de que alguien más encuentre algo útil.

Principales puntos problemáticos (es posible que ya me olvide de algunos):

  • La secuencia vacía da como resultado DateTime correspondiente a una fecha en Year 1, mientras que MinDateTime de Delphi está en Year 100.
  • Las cadenas con solo Fecha siempre se consideran UTC independientemente de la presencia o ausencia de ''Z'' o definiciones explícitas de huso horario.
  • Las cadenas con solo Time se identifican erróneamente como cadenas de fechas y se analizan incorrectamente.
  • Los modificadores de zona horaria se aplican SÓLO si están explícitamente definidos; de lo contrario, se asume que todos son UTC, incluso cuando no haya ''Z''.
  • Los segundos fraccionarios no son compatibles, sino que milisegundos siempre se convierten a 0.
  • Como las cadenas de tiempo únicas no son compatibles, tuve que agregarles una fecha ficticia y luego asegurarme de que es la fecha actual (para cubrir problemas de horario de verano al convertir a / desde UTC, que a su vez tuvo que realizarse debido a la UTC errónea consideraciones) y luego, al final, restarlo del resultado y, finalmente, en estos casos, garantizar el requisito de día cero para cadenas de tiempo único.

El resultado final es una función de aproximadamente 100 líneas (incluyendo comentarios, etc.), que utiliza una cantidad considerable de funciones auxiliares (que deberían ser bastante autoexplicativas y que no son el tema de este mensaje :)). Deshice los bits del código relevante en un archivo separado y la unidad prueba que usé para probar esto en otro, incluyo ambos a continuación. Siéntase libre de utilizar y comentar según sea necesario. Tenga en cuenta que el formulario y sus usos relacionados, etc. son exactamente lo que Delphi puso en el proyecto de demostración en el que lo incluí, de ninguna manera son necesarios.

unit Main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, XSBuiltIns, Math, DateUtils; const EPSILON = 10e-9; type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; {Returns whether the given variable represents negative infinity.} function IsNegInf(AValue : extended) : boolean; {Returns whether the given variable represents positive infinity.} function IsPosInf(AValue : extended) : boolean; {Checks the less than relation of the given real numbers (R1 < R2), up to precision EPSILON.} function RealLessThan(R1, R2 : double) : boolean; {Checks the greater than or equal to relation of the given real numbers (R1 >= R2), up to precision EPSILON.} function RealGreaterThanOrEqualTo(R1, R2 : double) : boolean; {Checks the less than or equal to relation of the given real numbers (R1 <= R2), up to precision EPSILON.} function RealLessThanOrEqualTo(R1, R2 : double) : boolean; {Return the floor of R, up to precision EPSILON. If Frac(R) < EPSILON, return R.} function RealFloor(R : extended) : extended; {Return the floor of R as integer, up to precision EPSILON. If Frac(R) < EPSILON, return R.} function RealFloorInt(R : extended) : integer; {Round the value X (properly) to an integer.} function RoundProper(X : extended) : integer; overload; function UtcTimeToLocalTime(AUtcTime: TDateTime): TDateTime; function LocalTimeToUtcTime(ALocalTime: TDateTime): TDateTime; function CountOccurrences(const SubText: string; const Text: string): Integer; // Returns a count of the number of occurences of SubText in Text function XMLTimeStamp2DateTime(TimeStamp : String): TDateTime; // Parses an XML time stamp string to a TDateTime. All returned times are in // local time. If time stamp string contains no time stamp definition (either // explicit time zone info or UTC flag), the time is assumed to be in local time. // Otherwise the time is parsed as the time zone indicated, and converted to local. // If no time section is contained in the stamp, the time is assumed to be // 0:00:00 in the time zone specified (or local time if no specification set). // If time string is not valid MinDateTime is returned. var Form1: TForm1; implementation {$R *.dfm} function XMLTimeStamp2DateTime(TimeStamp : String): TDateTime; var HasDateAndTimePart, HasUTCForce, HasExplicitTimeZone, HasDatePart, HasFractionalSeconds: Boolean; PlusCount, MinusCount, HourOffset, MinuteOffset, FractionIndex, I: Integer; TimeOffset: TDateTime; TimeZoneString, TimeZoneDelimiter: string; Year, Month, Day, MilliSeconds: Word; YearS, MonthS, DayS, FracSecS: string; CurrentDate, MSecsFromFractions: TDateTime; DotSeparatedDecimals: TFormatSettings; begin TimeOffset := 0; TimeZoneString := ''''; TimeZoneDelimiter := ''+''; FractionIndex := Pos(''.'', TimeStamp); {$REGION ''Get the fractional seconds as milliseconds''} HasFractionalSeconds := FractionIndex > 0; FracSecS := ''0.''; if HasFractionalSeconds then begin for I := FractionIndex + 1 to Length(TimeStamp) do begin if CharInSet(TimeStamp[I], [''0''..''9'']) then FracSecS := FracSecS + TimeStamp[I] else Break; end; end else FracSecS := FracSecS + ''0''; DotSeparatedDecimals.Create; DotSeparatedDecimals.DecimalSeparator := ''.''; DotSeparatedDecimals.ThousandSeparator := #0; MilliSeconds := RoundProper(StrToFloatDef(FracSecS, 0, DotSeparatedDecimals) * 1000); MSecsFromFractions := EncodeTime(0, 0, 0, MilliSeconds); {$ENDREGION} MinusCount := CountOccurrences(''-'', TimeStamp); HasDatePart := (MinusCount > 1) or (TimeStamp = ''''); PlusCount := CountOccurrences(''+'', TimeStamp); HasExplicitTimeZone := PlusCount > 0; if not HasExplicitTimeZone then begin HasExplicitTimeZone := Odd(MinusCount); // 1 or 3 minuses => explicit time zone TimeZoneDelimiter := ''-''; end; if HasExplicitTimeZone then begin TimeZoneString := Copy(TimeStamp, LastDelimiter(TimeZoneDelimiter, TimeStamp) + 1, Length(TimeStamp)); // Now TimeZoneString should be of format xx:xx where x''s are numbers! if (Length(TimeZoneString) = 5) and (TimeZoneString[3] = '':'') then begin HourOffset := StrToIntDef(Copy(TimeZoneString, 1, 2), 0); MinuteOffset := StrToIntDef(Copy(TimeZoneString, 3, 2), 0); TimeOffset := EncodeTime(HourOffset, MinuteOffset, 0, 0); if TimeZoneDelimiter = ''-'' then TimeOffset := -TimeOffset; end; end; CurrentDate := Now; Year := 0; Month := 0; Day := 0; DecodeDate(CurrentDate, Year, Month, Day); if not HasDatePart then begin // Since XMLTimeToDateTime doesn''t cope with strings without date part, add // a dummy one on current date if it doesn''t exist - we can''t use day zero // since then the daylight saving time calculation in the LocalTimeToUtcTime // fixup being possibly done later will go wrong, if local time is in DST // and day zero is not. So we have to use current day here, then remove it // from the final result once we''re done otherwise. YearS := IntToStr(Year); MonthS := IntToStr(Month); DayS := IntToStr(Day); while Length(YearS) < 4 do YearS := ''0'' + YearS; while Length(MonthS) < 2 do MonthS := ''0'' + MonthS; while Length(DayS) < 2 do DayS := ''0'' + DayS; TimeStamp := YearS + ''-'' + MonthS + ''-'' + DayS + SoapTimePrefix + TimeStamp; end; HasDateAndTimePart := Pos(SoapTimePrefix, TimeStamp) > 0; HasUTCForce := Pos(SLocalTimeMarker, TimeStamp) > 0; Result := XMLTimeToDateTime(TimeStamp); // This doesn''t support fractions of a second! // Now the conversion is done with zero milliseconds, we need to add the fractions Result := Result + MSecsFromFractions; // XMLTimeToDateTime assumes source as UTC when: // - No time part is defined and one of the following holds: // - Explicit time zone is defined (to other than UTC) - here it works WRONG! // - Explicit time zone is NOT defined and UTC flag is NOT defined - here it works WRONG! // - Explicit UTC flag is defined - here it works CORRECT! // - Time part is defined and one of the following holds: // - Explicit time zone is NOT defined and UTC flag is NOT defined - here it works WRONG! // - Explicit UTC flag is defined - here it works CORRECT! // In the cases where it works wrong, we need to manually offset its result // by the local-to-UTC difference. if (not HasExplicitTimeZone) and (not HasUTCForce) then Result := LocalTimeToUtcTime(Result) else if HasExplicitTimeZone and (not HasDateAndTimePart) then Result := Result - TimeOffset; // Minus to remove the effect of the offset if not HasDatePart then begin // We added the current date to make XMLTimeToDateTime work, now we need to // remove (the date part of) it back from the end result. Result := Result - EncodeDate(Year, Month, Day); // Since there originally was no date part, then there should not be one in // the end result also, meaning that the result''s date should correspond to // the zero-day. while RealGreaterThanOrEqualTo(Result, 1) do Result := Result - 1; while RealLessThan(Result, 0) do Result := Result + 1; end; Result := Max(Result, MinDateTime); // In erroneous situations XMLTimeToDateTime returns something less than MinDateTime, which we want as default end; { Returns a count of the number of occurences of SubText in Text } function CountOccurrences(const SubText: string; const Text: string): Integer; var i, j, SubLength: Integer; First: Char; begin Result := 0; if Length(SubText) <= 0 then Exit; First := SubText[1]; SubLength := Length(SubText); for i := 1 to Length(Text) do begin if Text[i] = First then begin j := 2; while (j <= SubLength) and (Text[i + j - 1] = SubText[j]) do Inc(j); if j > SubLength then Inc(result); // Matched all the way end; end; end; function UtcTimeToLocalTime(AUtcTime: TDateTime): TDateTime; begin Result := TTimeZone.Local.ToLocalTime(AUtcTime); end; function LocalTimeToUtcTime(ALocalTime: TDateTime): TDateTime; begin Result := TTimeZone.Local.ToUniversalTime(ALocalTime); end; function RoundProper(X : extended) : integer; begin Result := RealFloorInt(0.5 + x); end; function RealFloorInt(R : extended) : integer; begin Result := Trunc(RealFloor(R)); end; function RealFloor(R : extended) : extended; var FracR : Extended; begin Result := R; FracR := Abs(Frac(R)); if (FracR >= EPSILON) and RealLessThan(FracR, 1) then begin if Frac(R) > 0 then Result := R - Frac(R) else Result := R - (1 - Abs(Frac(R))); end; end; function RealLessThan(R1, R2 : double) : boolean; begin if IsPosInf(R2) then Result := not IsPosInf(R1) else if IsNegInf(R2) or IsPosInf(R1) then Result := False else if IsNegInf(R1) then Result := not IsNegInf(R2) else // (-Inf, -EPSILON) => Less, Result := R1 - R2 < -EPSILON; // [-EPSILON, EPSILON] => Equal end; // (EPSILON, Inf) => Greater function RealGreaterThanOrEqualTo(R1, R2 : double) : boolean; begin if IsPosInf(R1) or IsNegInf(R2) then Result := True else if IsPosInf(R2) or IsNegInf(R1) then Result := False else // (-Inf, -EPSILON) => Less, Result := R1 - R2 > -EPSILON; // [-EPSILON, EPSILON] => Equal end; // (EPSILON, Inf) => Greater function RealLessThanOrEqualTo(R1, R2 : double) : boolean; begin if IsPosInf(R2) or IsNegInf(R1) then Result := True else if IsPosInf(R1) or IsNegInf(R2) then Result := False else // (-Inf, -EPSILON) => Less, Result := R1 - R2 < EPSILON; // [-EPSILON, EPSILON] => Equal end; // (EPSILON, Inf) => Greater function IsPosInf(AValue : extended) : boolean; begin Result := IsInfinite(AValue) and (Sign(AValue) = 1); end; function IsNegInf(AValue : extended) : boolean; begin Result := IsInfinite(AValue) and (Sign(AValue) = -1); end; end.

Entonces las pruebas unitarias están aquí:

unit TestMain; { Delphi DUnit Test Case ---------------------- This unit contains a skeleton test case class generated by the Test Case Wizard. Modify the generated code to correctly setup and call the methods from the unit being tested. } interface uses TestFramework, System.SysUtils, Vcl.Graphics, XSBuiltIns, Winapi.Windows, System.Variants, DateUtils, Vcl.Dialogs, Vcl.Controls, Vcl.Forms, Winapi.Messages, Math, System.Classes, Main; type // Test methods for class TForm1 TestTForm1 = class(TTestCase) strict private public procedure SetUp; override; procedure TearDown; override; published procedure TestXMLTimeStamp2DateTime; end; implementation procedure TestTForm1.SetUp; begin // Nothing to do here end; procedure TestTForm1.TearDown; begin // Nothing to do here end; procedure TestTForm1.TestXMLTimeStamp2DateTime; const TIME_TOLERANCE = 0.0000000115741; // Approximately 1 millisecond, in days var Source: string; ReturnValue, ExpectedValue, Today: TDateTime; function DateTimeOfToday: TDateTime; var Year, Month, Day: Word; begin Year := 0; Month := 0; Day := 0; DecodeDate(Now, Year, Month, Day); Result := EncodeDate(Year, Month, Day); end; begin Today := DateTimeOfToday; // Counted only once, we ignore the theoretic chance of day changing during the test execution from DST to non-DST or vice versa {$REGION ''Empty string''} // Setup method call parameters Source := ''''; ExpectedValue := MinDateTime; // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for empty string should return MinDateTime, but did not!''); {$ENDREGION} {$REGION ''Date only strings''} {$REGION ''Date string - local''} // Setup method call parameters Source := ''2002-09-24''; ExpectedValue := EncodeDate(2002, 9, 24); // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, ''XMLTimeStamp2DateTime for date string - local should return 24.9.2002, but did not!''); {$ENDREGION} {$REGION ''Date string - UTC''} // Setup method call parameters Source := ''2002-09-24Z''; ExpectedValue := EncodeDate(2002, 9, 24); ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date string - UTC should return 24.9.2002 + local time offset, but did not!''); {$ENDREGION} {$REGION ''Date string - negative offset''} // Setup method call parameters Source := ''2002-09-24-03:00''; ExpectedValue := EncodeDate(2002, 9, 24); ExpectedValue := ExpectedValue + EncodeTime(3, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date string - negative offset should return 24.9.2002 + three hours + local time offset, but did not!''); {$ENDREGION} {$REGION ''Date string - positive offset''} // Setup method call parameters Source := ''2002-09-24+11:00''; ExpectedValue := EncodeDate(2002, 9, 24); ExpectedValue := ExpectedValue - EncodeTime(11, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date string - positive offset should return 24.9.2002 - eleven hours + local time offset, but did not!''); {$ENDREGION} {$ENDREGION} {$REGION ''Time only strings''} {$REGION ''Time string - local''} // Setup method call parameters Source := ''09:30:10''; ExpectedValue := EncodeTime(9, 30, 10, 0); // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for time string - local should return 09:30:10, but did not!''); {$ENDREGION} {$REGION ''Time string - UTC''} // Setup method call parameters Source := ''09:30:10Z''; // Have to add Today for the UtcTimeToLocalTime call to have correct DST // - then have to remove Today again away to have correct zero-day date ExpectedValue := Today + EncodeTime(9, 30, 10, 0); ExpectedValue := UtcTimeToLocalTime(ExpectedValue); ExpectedValue := ExpectedValue - Today; // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for time string - UTC should return 09:30:10 + local time offset, but did not!''); {$ENDREGION} {$REGION ''Time string - negative offset''} // Setup method call parameters Source := ''09:30:10-03:00''; // Have to add Today for the UtcTimeToLocalTime call to have correct DST // - then have to remove Today again away to have correct zero-day date ExpectedValue := Today + EncodeTime(9, 30, 10, 0); ExpectedValue := ExpectedValue + EncodeTime(3, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC ExpectedValue := ExpectedValue - Today; // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for time string - negative offset should return 09:30:10 + three hours + local time offset, but did not!''); {$ENDREGION} {$REGION ''Time string - positive offset over date line''} // Setup method call parameters Source := ''06:30:10+11:00''; // Have to add Today for the UtcTimeToLocalTime call to have correct DST // - then have to remove Today again away to have correct zero-day date ExpectedValue := Today + EncodeTime(6, 30, 10, 0); ExpectedValue := ExpectedValue - EncodeTime(11, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC ExpectedValue := ExpectedValue - Today; if RealGreaterThanOrEqualTo(ExpectedValue, 1) then ExpectedValue := ExpectedValue - 1; // When having time only, date should always be zero! if RealLessThan(ExpectedValue, 0) then ExpectedValue := ExpectedValue + 1; // When having time only, date should always be zero! // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for time string - positive offset (over day change) should return 06:30:10 - eleven hours + local time offset (modulo 24 hours), but did not!''); {$ENDREGION} {$REGION ''Fractional time string with negative offset over date line''} // Setup method call parameters Source := ''14:30:10.25-11:00''; // Have to add Today for the UtcTimeToLocalTime call to have correct DST // - then have to remove Today again away to have correct zero-day date ExpectedValue := Today + EncodeTime(14, 30, 10, 250); ExpectedValue := ExpectedValue + EncodeTime(11, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC ExpectedValue := ExpectedValue - Today; if RealGreaterThanOrEqualTo(ExpectedValue, 1) then ExpectedValue := ExpectedValue - 1; // When having time only, date should always be zero! if RealLessThanOrEqualTo(ExpectedValue, 0) then ExpectedValue := ExpectedValue + 1; // When having time only, date should always be zero! // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for fractional time string - negative offset (over day change) should return 14:30:10.25 + eleven hours + local time offset (modulo 24 hours), but did not!''); {$ENDREGION} {$ENDREGION} {$REGION ''Date and time strings} {$REGION ''Date and time string - local''} // Setup method call parameters Source := ''2002-09-24T09:30:10.25''; ExpectedValue := EncodeDate(2002, 9, 24) + EncodeTime(9, 30, 10, 250); // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date and time string - local should return 24.9.2002 09:30:10.25, but did not!''); {$ENDREGION} {$REGION ''Date and time string - UTC''} // Setup method call parameters Source := ''2002-09-24T09:30:10.25Z''; ExpectedValue := EncodeDate(2002, 9, 24) + EncodeTime(9, 30, 10, 250); ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date and time string - UTC should return 24.9.2002 09:30:10.25 + local time offset, but did not!''); {$ENDREGION} {$REGION ''Date and time string - positive offset over date line''} // Setup method call parameters Source := ''2002-09-24T06:30:10.25+11:00''; ExpectedValue := EncodeDate(2002, 9, 24) + EncodeTime(6, 30, 10, 250); ExpectedValue := ExpectedValue - EncodeTime(11, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date and time string - positive offset (over day change) should return 24.9.2002 06:30:10.25 - eleven hours + local time offset, but did not!''); {$ENDREGION} {$REGION ''Date and time string - negative offset over date line''} // Setup method call parameters Source := ''2002-09-24T14:30:10.25-11:00''; ExpectedValue := EncodeDate(2002, 9, 24) + EncodeTime(14, 30, 10, 250); ExpectedValue := ExpectedValue + EncodeTime(11, 0, 0, 0); // First convert to UTC by removing the offset ExpectedValue := UtcTimeToLocalTime(ExpectedValue); // Then convert to local from UTC // Call the method ReturnValue := XMLTimeStamp2DateTime(Source); // Validate method results CheckEquals(ExpectedValue, ReturnValue, TIME_TOLERANCE, ''XMLTimeStamp2DateTime for date and time string - negative offset (over day change) should return 14:30:10.25 + eleven hours + local time offset, but did not!''); {$ENDREGION} {$ENDREGION} end; initialization // Register any test cases with the test runner RegisterTest(TestTForm1.Suite); end.


La unidad OmniXML OmniXMLUtils contiene un montón de funciones para hacer XML para fechar y fechar las conversiones XML.

function XMLStrToDateTime(nodeValue: XmlString; var value: TDateTime): boolean; overload; function XMLStrToDateTime(nodeValue: XmlString): TDateTime; overload; function XMLStrToDateTimeDef(nodeValue: XmlString; defaultValue: TDateTime): TDateTime; function XMLStrToDate(nodeValue: XmlString; var value: TDateTime): boolean; overload; function XMLStrToDate(nodeValue: XmlString): TDateTime; overload; function XMLStrToDateDef(nodeValue: XmlString; defaultValue: TDateTime): TDateTime; function XMLStrToTime(nodeValue: XmlString; var value: TDateTime): boolean; overload; function XMLStrToTime(nodeValue: XmlString): TDateTime; overload; function XMLStrToTimeDef(nodeValue: XmlString; defaultValue: TDateTime): TDateTime; function XMLDateTimeToStr(value: TDateTime): XmlString; function XMLDateTimeToStrEx(value: TDateTime): XmlString; function XMLDateToStr(value: TDateTime): XmlString; function XMLTimeToStr(value: TDateTime): XmlString;