unixandroid.inc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2016 by Yury Sidorov,
  4. member of the Free Pascal development team.
  5. Android-specific part of the System unit.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. type
  13. UErrorCode = SizeInt;
  14. int32_t = longint;
  15. uint32_t = longword;
  16. UBool = LongBool;
  17. UCalendar = pointer;
  18. UCalendarType = longint;
  19. UCalendarDisplayNameType = longint;
  20. UCalendarDateFields = longint;
  21. const
  22. UCAL_STANDARD = 0;
  23. UCAL_SHORT_STANDARD = 1;
  24. UCAL_DST = 2;
  25. UCAL_SHORT_DST = 3;
  26. UCAL_ZONE_OFFSET = 15;
  27. UCAL_DST_OFFSET = 16;
  28. var
  29. ucal_open: function (zoneID: PUnicodeChar; len: int32_t; locale: PAnsiChar; ctype: UCalendarType; var status: UErrorCode): UCalendar; cdecl;
  30. ucal_close: procedure (cal: UCalendar); cdecl;
  31. ucal_getTimeZoneDisplayName: function (cal: UCalendar; dtype: UCalendarDisplayNameType; locale: PAnsiChar; result: PUnicodeChar; resultLength: int32_t;
  32. var status: UErrorCode): int32_t; cdecl;
  33. ucal_inDaylightTime: function (cal: UCalendar; var status: UErrorCode): UBool; cdecl;
  34. ucal_get: function (cal: UCalendar; field: UCalendarDateFields; var status: UErrorCode): int32_t; cdecl;
  35. GetIcuProc: function (const Name: AnsiString; var ProcPtr; libId: longint): boolean; external name 'ANDROID_GET_ICU_PROC';
  36. procedure ReadTimeZoneFromICU;
  37. var
  38. locale: utf8string;
  39. tz: unicodestring;
  40. res: unicodestring;
  41. TZStandardName: utf8string;
  42. TZDaylightName: utf8string;
  43. err: UErrorCode;
  44. cal: UCalendar;
  45. lTZInfo: TTZInfo;
  46. lTZInfoEx: TTZInfoEx;
  47. begin
  48. if not Assigned(GetIcuProc) then exit;
  49. if not GetIcuProc('ucal_open', ucal_open, 1) then exit;
  50. if not GetIcuProc('ucal_close', ucal_close, 1) then exit;
  51. if not GetIcuProc('ucal_getTimeZoneDisplayName', ucal_getTimeZoneDisplayName, 1) then exit;
  52. if not GetIcuProc('ucal_inDaylightTime', ucal_inDaylightTime, 1) then exit;
  53. if not GetIcuProc('ucal_get', ucal_get, 1) then exit;
  54. locale:='en_US';
  55. tz:=unicodestring(GetSystemProperty('persist.sys.timezone'));
  56. err:=0;
  57. cal:=ucal_open(PUnicodeChar(tz), Length(tz), PAnsiChar(locale), 0, err);
  58. if cal = nil then
  59. exit;
  60. lTzinfo.daylight:=ucal_inDaylightTime(cal, err);
  61. SetLength(res, 200);
  62. SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_STANDARD, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
  63. TZStandardName:=utf8string(res);
  64. lTZInfoEx.name[False]:=TZStandardName;
  65. SetLength(res, 200);
  66. SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_DST, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
  67. TZDaylightName:=utf8string(res);
  68. lTZInfoEx.name[True]:=TZDaylightName;
  69. lTZInfoEx.leap_correct:=0;
  70. lTZInfoEx.leap_hit:=0;
  71. lTZInfo.seconds:=ucal_get(cal, UCAL_ZONE_OFFSET, err) div 1000;
  72. if lTZInfo.daylight then
  73. lTZInfo.seconds:=Tzinfo.seconds + ucal_get(cal, UCAL_DST_OFFSET, err) div 1000;
  74. // ToDo: correct validsince/validuntil values
  75. lTZInfo.validsince:=low(lTZInfo.validsince);
  76. lTZInfo.validuntil:=high(lTZInfo.validuntil);
  77. SetTZInfo(lTZInfo, lTZInfoEx);
  78. ucal_close(cal);
  79. end;
  80. type
  81. Ptm = ^tm;
  82. tm = record
  83. tm_sec : longint;
  84. tm_min : longint;
  85. tm_hour : longint;
  86. tm_mday : longint;
  87. tm_mon : longint;
  88. tm_year : longint;
  89. tm_wday : longint;
  90. tm_yday : longint;
  91. tm_isdst : longint;
  92. case boolean of
  93. false : (tm_gmtoff : longint;tm_zone : Pchar);
  94. true : (__tm_gmtoff : longint;__tm_zone : Pchar);
  95. end;
  96. function localtime(t: Ptime_t): Ptm; cdecl; external 'c' name 'localtime';
  97. var
  98. c_tzname: array[0..1] of PAnsiChar; external 'c' name 'tzname';
  99. function ReadTimeZoneFromLibC: boolean;
  100. var
  101. t: time_t;
  102. tt: Ptm;
  103. lTZInfo: TTZInfo;
  104. lTZInfoEx: TTZInfoEx;
  105. begin
  106. ReadTimeZoneFromLibC:=False;
  107. lTZInfo:=default(TTZInfo);
  108. lTZInfoEx:=default(TTZInfoEx);
  109. lTZInfoEx.name[false]:=c_tzname[0];
  110. lTZInfoEx.name[true]:=c_tzname[1];
  111. t:=fptime;
  112. tt:=localtime(@t);
  113. if tt <> nil then
  114. begin
  115. lTZInfo.daylight:=tt^.tm_isdst <> 0;
  116. lTZInfo.seconds:=tt^.tm_gmtoff;
  117. // ToDo: correct validsince/validuntil values
  118. lTZInfo.validsince:=low(lTZInfo.validsince);
  119. lTZInfo.validuntil:=high(lTZInfo.validuntil);
  120. SetTZInfo(lTZInfo, lTZInfoEx);
  121. ReadTimeZoneFromLibC:=lTZInfoEx.name[false] <> '';
  122. end;
  123. end;
  124. procedure InitLocalTime;
  125. begin
  126. if (SystemApiLevel <= 10) or not ReadTimeZoneFromLibC then
  127. // If current Android version is too old and does not support timezone
  128. // in libc, use ICU library.
  129. ReadTimeZoneFromICU;
  130. end;