unixandroid.inc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. var
  36. TZStandardName: utf8string;
  37. TZDaylightName: utf8string;
  38. GetIcuProc: function (const Name: AnsiString; var ProcPtr; libId: longint): boolean; external name 'ANDROID_GET_ICU_PROC';
  39. procedure ReadTimeZoneFromICU;
  40. var
  41. locale: utf8string;
  42. tz: unicodestring;
  43. res: unicodestring;
  44. err: UErrorCode;
  45. cal: UCalendar;
  46. begin
  47. if not Assigned(GetIcuProc) then exit;
  48. if not GetIcuProc('ucal_open', ucal_open, 1) then exit;
  49. if not GetIcuProc('ucal_close', ucal_close, 1) then exit;
  50. if not GetIcuProc('ucal_getTimeZoneDisplayName', ucal_getTimeZoneDisplayName, 1) then exit;
  51. if not GetIcuProc('ucal_inDaylightTime', ucal_inDaylightTime, 1) then exit;
  52. if not GetIcuProc('ucal_get', ucal_get, 1) then exit;
  53. locale:='en_US';
  54. tz:=unicodestring(GetSystemProperty('persist.sys.timezone'));
  55. err:=0;
  56. cal:=ucal_open(PUnicodeChar(tz), Length(tz), PAnsiChar(locale), 0, err);
  57. if cal = nil then
  58. exit;
  59. Tzinfo.daylight:=ucal_inDaylightTime(cal, err);
  60. SetLength(res, 200);
  61. SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_STANDARD, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
  62. TZStandardName:=utf8string(res);
  63. Tzinfo.name[False]:=PAnsiChar(TZStandardName);
  64. SetLength(res, 200);
  65. SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_DST, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
  66. TZDaylightName:=utf8string(res);
  67. Tzinfo.name[True]:=PAnsiChar(TZDaylightName);
  68. Tzinfo.seconds:=ucal_get(cal, UCAL_ZONE_OFFSET, err) div 1000;
  69. if Tzinfo.daylight then
  70. Tzinfo.seconds:=Tzinfo.seconds + ucal_get(cal, UCAL_DST_OFFSET, err) div 1000;
  71. // ToDo: correct validsince/validuntil values
  72. Tzinfo.validsince:=low(Tzinfo.validsince);
  73. Tzinfo.validuntil:=high(Tzinfo.validuntil);
  74. ucal_close(cal);
  75. end;
  76. type
  77. Ptm = ^tm;
  78. tm = record
  79. tm_sec : longint;
  80. tm_min : longint;
  81. tm_hour : longint;
  82. tm_mday : longint;
  83. tm_mon : longint;
  84. tm_year : longint;
  85. tm_wday : longint;
  86. tm_yday : longint;
  87. tm_isdst : longint;
  88. case boolean of
  89. false : (tm_gmtoff : longint;tm_zone : Pchar);
  90. true : (__tm_gmtoff : longint;__tm_zone : Pchar);
  91. end;
  92. function localtime(t: Ptime_t): Ptm; cdecl; external 'c' name 'localtime';
  93. var
  94. c_tzname: array[0..1] of PAnsiChar; external 'c' name 'tzname';
  95. function ReadTimeZoneFromLibC: boolean;
  96. var
  97. t: time_t;
  98. tt: Ptm;
  99. begin
  100. ReadTimeZoneFromLibC:=False;
  101. tzname[false]:=c_tzname[0];
  102. tzname[true]:=c_tzname[1];
  103. t:=fptime;
  104. tt:=localtime(@t);
  105. if tt <> nil then
  106. begin
  107. tzdaylight:=tt^.tm_isdst <> 0;
  108. tzseconds:=tt^.tm_gmtoff;
  109. ReadTimeZoneFromLibC:=tzname[false] <> nil;
  110. end;
  111. end;
  112. procedure InitLocalTime;
  113. begin
  114. if (SystemApiLevel <= 10) or not ReadTimeZoneFromLibC then
  115. // If current Android version is too old and does not support timezone
  116. // in libc, use ICU library.
  117. ReadTimeZoneFromICU;
  118. end;