|
Registriert seit: 13. Jan 2004 Ort: Hamm(Westf) 1.996 Beiträge Delphi 12 Athens |
#1
(Android) Fehler in DateUtils behoben // TTimezone.Local.ID // Ich bitte um Prüfung![]()
Wenn man
TTimezone.Local.ID innerhalb einer 64Bit Android App abruft, dann meldet die APP in Deutschland als Zeitzonen-ID "ET" . Das ist "Eastern Time" alias "Eastern Standard Time" alias "EST". Korrekt wäre es, wenn als Zeitzone "CET"(deprecated) oder "Europe/Berlin" gemeldet würde Selbst wenn ich die Zeitzone nach Portugal verlege, meldet die App dann nicht "WET" was korrekt wäre, sondern auch "ET" als Zeitzone. Sprich der erste Buchstabe geht verloren! *ARRRGH* Die App denkt also immer sie wäre in einer US-Zeitzone, weil es "ET" in meiner Datenbank tatsächlich gibt.... Ich habe also die Codestellen in der unit DateUtils.pas die diesen Code benutzen: Einstring := Utf8ToString(LChars) In folgenden Code geändert: Einstring := Trim(TEncoding.UTF8.GetString(LChars)) ; Das Trim ist notwendig sonst funktionieren die Vergleiche nicht... Vermutlich wäre es besser gewesen Utf8ToString zu fixen, aber ich habe mich das nicht getraut und ich habe die Typen rawstring usw. nicht auf Anhieb verstanden. Bitte sagt mir ob die Anpassung in Ordnung ist. Soll ich das über meine Firma an die QC weitergeben oder ist das Problem schon von Emba gelöst? Listing der ganzen Funktion in der 3 Stellen geöndert wurden. (nach "Korrektur" ohne Gänsefüßchen suchen)
Delphi-Quellcode:
function TLocalTimeZone.GetChangesForYear(const AYear: Word): PYearlyChanges;
{$IF defined(MSWINDOWS)} function GetAbsoluteDateFromRule(const AYear, AMonth, ADoW, ADoWIndex: Word; AToD: TTime): TDateTime; const CReDoW: array [0 .. 6] of Integer = (7, 1, 2, 3, 4, 5, 6); var LExpDayOfWeek, LActualDayOfWeek: Word; begin { No actual rule } if (AMonth = 0) and (ADoW = 0) and (ADoWIndex = 0) then Exit(0); { Transform into ISO 8601 day of week } LExpDayOfWeek := CReDoW[ADoW]; { Generate a date in the form of: Year/Month/1st of month } Result := EncodeDate(AYear, AMonth, 1); { Get the day of week for this newly crafted date } LActualDayOfWeek := DayOfTheWeek(Result); { We're too far off now, let's decrease the number of days till we get to the desired one } if LActualDayOfWeek > LExpDayOfWeek then Result := IncDay(Result, DaysPerWeek - LActualDayOfWeek + LExpDayOfWeek) else if (LActualDayOfWeek < LExpDayOfWeek) Then Result := IncDay(Result, LExpDayOfWeek - LActualDayOfWeek); { Skip the required number of weeks } Result := IncDay(Result, DaysPerWeek * (ADoWIndex - 1)); { If we've skipped the day in this moth, go back a few weeks until we get it right again } while (MonthOf(Result) > AMonth) do Result := IncDay(Result, -DaysPerWeek); { Add the time part } Result := Result + AToD; end; var LTZ: TTimeZoneInformation; LResult: Cardinal; begin Result := AllocMem(SizeOf(TYearlyChanges)); LTZ := Default(TTimeZoneInformation); { Win32 can't handle dates outside this range } if (AYear <= 1601) or (AYear > 30827) then exit; { Use either Vista of lower APIs. If Vista one fails, also use the lower API. } if TOSVersion.Check(6, 1, 1) and GetTimeZoneInformationForYear(AYear, nil, LTZ) then LResult := TIME_ZONE_ID_STANDARD else LResult := GetTimeZoneInformation(LTZ); { Try with the old API } { Exit on error } if LResult = TIME_ZONE_ID_INVALID then exit; { Try to obtain the daylight adjustment for the specified year } if LResult <> TIME_ZONE_ID_UNKNOWN then begin with LTZ.StandardDate do Result.FEndOfDST := GetAbsoluteDateFromRule(AYear, wMonth, wDayOfWeek, wDay, EncodeTime(wHour, wMinute, wSecond, 0)); with LTZ.DaylightDate do Result.FStartOfDST := GetAbsoluteDateFromRule(AYear, wMonth, wDayOfWeek, wDay, EncodeTime(wHour, wMinute, wSecond, 0)); end; Result.FBias := -SecsPerMin * (LTZ.StandardBias + LTZ.Bias); Result.FBiasWithDST := -SecsPerMin * (LTZ.DaylightBias + LTZ.Bias); Result.FName := LTZ.StandardName; Result.FDSTName := LTZ.DaylightName; end; {$ELSEIF defined(MACOS)} function MacToDateTime(const AbsTime: CFAbsoluteTime; const ATZ: CFTimeZoneRef): TDateTime; var LDate: CFGregorianDate; begin { Decompose the object } LDate := CFAbsoluteTimeGetGregorianDate(AbsTime, ATZ); { Generate a TDateTime now } with LDate do Result := EncodeDateTime(year, month, day, hour, minute, Round(second), 0); end; procedure CopyInfo(const ATZ: CFTimeZoneRef; const AStartBT: CFAbsoluteTime; out LPt1DT, LPt2DT: TDateTime; out LPt1Off, LPt2Off: Int64); var L1stTrans, L2ndTrans: CFAbsoluteTime; begin { Calculate the first and the last transition times } L1stTrans := CFTimeZoneGetNextDaylightSavingTimeTransition(ATZ, AStartBT); L2ndTrans := CFTimeZoneGetNextDaylightSavingTimeTransition(ATZ, L1stTrans); { Obtain the GMT offset before first transition } LPt1Off := Round(CFTimeZoneGetSecondsFromGMT(ATZ, AStartBT)); if (L1stTrans <> 0) or (L2ndTrans > L1stTrans) then begin { Convert the first transition to TDateTime } LPt1DT := MacToDateTime(L1stTrans, ATZ); { Convert the second transition to TDateTime } LPt2DT := MacToDateTime(L2ndTrans, ATZ); { Obtain the GMT offset before second transition } LPt2Off := Round(CFTimeZoneGetSecondsFromGMT(ATZ, L1stTrans)); end else begin { There were no transitions. Use the base data } LPt2Off := LPt1Off; LPt1DT := MacToDateTime(AStartBT, ATZ); LPt2DT := LPt1DT; end; end; var LLocaleRef: CFLocaleRef; L1stJan: CFAbsoluteTime; LDate: CFGregorianDate; { What we expect } LStart, LEnd: TDateTime; begin { Create the changes block. Keep it clean so far. } Result := AllocMem(SizeOf(TYearlyChanges)); if FTZ <> nil then begin { Encode 1st Jan of the given year into Absolute time } with LDate do begin year := AYear; month := MonthJanuary; day := 1; hour := 0; minute := 0; second := 0; end; { Generate an absolute time (1st Jan Year) } L1stJan := CFGregorianDateGetAbsoluteTime(LDate, FTZ); { Use CopyInfo but reverse the variables depending on the Northern/Southern hemispheres } if not CFTimeZoneIsDaylightSavingTime(FTZ, L1stJan) then CopyInfo(FTZ, L1stJan, LStart, LEnd, Result.FBias, Result.FBiasWithDST) else CopyInfo(FTZ, L1stJan, LEnd, LStart, Result.FBiasWithDST, Result.FBias); { Fill the remaining parts of the structure } LLocaleRef := CFLocaleCopyCurrent(); if LLocaleRef <> nil then begin { Obtain localized names of the locale (normal and DST) } try Result.FName := TCFString(CFTimeZoneCopyLocalizedName(FTZ, kCFTimeZoneNameStyleStandard, LLocaleRef)).AsString(True); Result.FDSTName := TCFString(CFTimeZoneCopyLocalizedName(FTZ, kCFTimeZoneNameStyleDaylightSaving, LLocaleRef)).AsString(True); finally CFRelease(LLocaleRef); end; end else begin { Fall back to std info } Result.FName := TCFString(CFTimeZoneGetName(FTZ)); Result.FDSTName := Result.FName; end; Result.FStartOfDST := IncSecond(LStart, Result.FBias - Result.FBiasWithDST); // Remove the save time from result Result.FEndOfDST := IncSecond(LEnd, Result.FBiasWithDST - Result.FBias); // Add the save time to result end; end; {$ELSEIF defined(POSIX)} var LComp: tm; LTime: time_t; LLastOffset, LDay: Integer; LIsSecondCycle, LIsStandard: Boolean; LChars: TBytes; begin SetLength(LChars, 256); { Create the changes block. Keep it clean so far. } Result := AllocMem(SizeOf(TYearlyChanges)); if (SizeOf(LongInt) = 4) and ((AYear < 1970) or (AYear > 2037)) then Exit; // Not supported { Generate a value that starts with 1st of the current year } FillChar(LComp, SizeOf(LComp), 0); LComp.tm_mday := 1; LComp.tm_year := AYear - 1900; LTime := mktime(LComp); if LTime = -1 then Exit; // Some error occured! { Unknown DST information. Quit. } if LComp.tm_isdst < -1 then Exit; { Check if the DST or STD time was in effect at 1st Jan } LIsStandard := LComp.tm_isdst = 0; { Prepare to iterate over the year } LLastOffset := LComp.tm_gmtoff; LIsSecondCycle := false; { Initialize info, in some locales like Russia and in some years the clock is not changed for daylight saving } Result.FStartOfDST := IncSecond(FileDateToDateTime(LTime), LLastOffset - LComp.tm_gmtoff); Result.FEndOfDST := Result.FStartOfDST; Result.FBias := LLastOffset; Result.FDSTName := ''; Result.FBiasWithDST := LLastOffset; strftime(MarshaledAString(LChars), Length(LChars), '%Z', LComp); // DO NOT LOCALIZE Result.FName := Trim(TEncoding.UTF8.GetString(LChars));//<----- Korrektur Alter Code----> // Result.FName := Utf8ToString(LChars); for LDay := 0 to DaysInAYear(AYear) - 1 do begin { Skip to next day } Inc(LTime, SecsPerDay); { Decompose the time } if localtime_r(LTime, LComp) <> @LComp then Exit; if LComp.tm_gmtoff <> LLastOffset then begin { We found the day when the time change occured. Serach the hour now. } repeat Dec(LTime, SecsPerHour); { Decompose the time } if localtime_r(LTime, LComp) <> @LComp then Exit; until LComp.tm_gmtoff = LLastOffset; { Search for the minute } repeat Inc(LTime, SecsPerMin); { Decompose the time } if localtime_r(LTime, LComp) <> @LComp then Exit; until LComp.tm_gmtoff <> LLastOffset; { Generate the time zone abbreviation } strftime(MarshaledAString(LChars), Length(LChars), '%Z', LComp); // DO NOT LOCALIZE if LIsStandard then begin { We were in the standard period } Result.FStartOfDST := IncSecond(FileDateToDateTime(LTime), LLastOffset - LComp.tm_gmtoff); Result.FBias := LLastOffset; Result.FDSTName := Trim(TEncoding.UTF8.GetString(LChars));//<----- Korrektur Alter Code----> //Result.FDSTName := Utf8ToString(LChars); end else begin { We were in the DST period } Result.FEndOfDST := IncSecond(FileDateToDateTime(LTime), LLastOffset - LComp.tm_gmtoff); Result.FBiasWithDST := LLastOffset; Result.FName := Trim(TEncoding.UTF8.GetString(LChars));//<----- Korrektur Alter Code----> //Result.FName := Utf8ToString(LChars); end; { Set the last offset } LLastOffset := LComp.tm_gmtoff; LIsStandard := not LIsStandard; { Die if this is the second cycle } if LIsSecondCycle then Exit else LIsSecondCycle := true; end; end; end; {$ENDIF}
Andreas
Monads? Wtf are Monads? Geändert von QuickAndDirty (20. Jul 2020 um 14:53 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |