* android: Use ICU to get timezone information if running on an Android version where libc does not implement timezone.

git-svn-id: trunk@34348 -
This commit is contained in:
yury 2016-08-19 14:57:02 +00:00
parent f50671fe44
commit 064375ea72
4 changed files with 94 additions and 15 deletions

View File

@ -3572,7 +3572,7 @@ endif
.NOTPARALLEL:
include $(INC)/makefile.inc
SYSINCDEPS=$(addprefix $(INC)/,$(SYSINCNAMES))
SYSINCDEPS:=$(SYSINCDEPS) sysandroid.inc
SYSINCDEPS:=$(SYSINCDEPS) sysandroidh.inc sysandroid.inc
include $(PROCINC)/makefile.cpu
SYSCPUDEPS=$(addprefix $(PROCINC)/,$(CPUINCNAMES))
SYSDEPS=$(SYSINCDEPS) $(SYSCPUDEPS)
@ -3598,7 +3598,7 @@ strings$(PPUEXT) : $(INC)/strings.pp $(INC)/stringsi.inc\
$(COMPILER) $(INC)/strings.pp
unix$(PPUEXT) : $(UNIXINC)/unix.pp strings$(PPUEXT) baseunix$(PPUEXT) $(INC)/textrec.inc $(INC)/filerec.inc \
$(LINUXINC)/unxconst.inc $(UNIXINC)/timezone.inc $(SYSTEMUNIT)$(PPUEXT) \
$(LINUXINC)/unxfunc.inc unixandroid.inc
$(LINUXINC)/unxfunc.inc unixandroid.inc cwstring$(PPUEXT)
$(COMPILER) $(UNIXINC)/unix.pp
syscall$(PPUEXT) : $(UNIXINC)/syscall.pp $(LINUXINC)/$(ARCH)/syscallh.inc $(LINUXINC)/$(ARCH)/sysnr.inc $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/syscall.pp
@ -3612,7 +3612,7 @@ baseunix$(PPUEXT) : $(UNIXINC)/baseunix.pp $(LINUXINC)/errno.inc $(LINUXINC)/pty
$(LINUXINC)/ostypes.inc $(LINUXINC)/osmacro.inc $(UNIXINC)/gensigset.inc \
$(UNIXINC)/genfuncs.inc $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/baseunix.pp
dl$(PPUEXT) : $(UNIXINC)/dl.pp $(SYSTEMUNIT)$(PPUEXT) dlandroid.inc
dl$(PPUEXT) : $(UNIXINC)/dl.pp $(SYSTEMUNIT)$(PPUEXT) ctypes$(PPUEXT) dlandroid.inc
$(COMPILER) $(UNIXINC)/dl.pp
dynlibs$(PPUEXT) : $(INC)/dynlibs.pas $(UNIXINC)/dynlibs.inc dl$(PPUEXT) objpas$(PPUEXT)
$(COMPILER) $(INC)/dynlibs.pas

View File

@ -83,7 +83,7 @@ OBJPASDIR=$(RTL)/objpas
# SYSINCNAMES
include $(INC)/makefile.inc
SYSINCDEPS=$(addprefix $(INC)/,$(SYSINCNAMES))
SYSINCDEPS:=$(SYSINCDEPS) sysandroid.inc
SYSINCDEPS:=$(SYSINCDEPS) sysandroidh.inc sysandroid.inc
# Get the processor dependent include file names.
# This will set the following variables :
@ -139,7 +139,7 @@ strings$(PPUEXT) : $(INC)/strings.pp $(INC)/stringsi.inc\
unix$(PPUEXT) : $(UNIXINC)/unix.pp strings$(PPUEXT) baseunix$(PPUEXT) $(INC)/textrec.inc $(INC)/filerec.inc \
$(LINUXINC)/unxconst.inc $(UNIXINC)/timezone.inc $(SYSTEMUNIT)$(PPUEXT) \
$(LINUXINC)/unxfunc.inc unixandroid.inc
$(LINUXINC)/unxfunc.inc unixandroid.inc cwstring$(PPUEXT)
$(COMPILER) $(UNIXINC)/unix.pp
syscall$(PPUEXT) : $(UNIXINC)/syscall.pp $(LINUXINC)/$(ARCH)/syscallh.inc $(LINUXINC)/$(ARCH)/sysnr.inc $(SYSTEMUNIT)$(PPUEXT)
@ -158,7 +158,7 @@ baseunix$(PPUEXT) : $(UNIXINC)/baseunix.pp $(LINUXINC)/errno.inc $(LINUXINC)/pty
$(UNIXINC)/genfuncs.inc $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/baseunix.pp
dl$(PPUEXT) : $(UNIXINC)/dl.pp $(SYSTEMUNIT)$(PPUEXT) dlandroid.inc
dl$(PPUEXT) : $(UNIXINC)/dl.pp $(SYSTEMUNIT)$(PPUEXT) ctypes$(PPUEXT) dlandroid.inc
$(COMPILER) $(UNIXINC)/dl.pp
dynlibs$(PPUEXT) : $(INC)/dynlibs.pas $(UNIXINC)/dynlibs.inc dl$(PPUEXT) objpas$(PPUEXT)

View File

@ -13,6 +13,79 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
type
UErrorCode = SizeInt;
int32_t = longint;
uint32_t = longword;
UBool = LongBool;
UCalendar = pointer;
UCalendarType = longint;
UCalendarDisplayNameType = longint;
UCalendarDateFields = longint;
const
UCAL_STANDARD = 0;
UCAL_SHORT_STANDARD = 1;
UCAL_DST = 2;
UCAL_SHORT_DST = 3;
UCAL_ZONE_OFFSET = 15;
UCAL_DST_OFFSET = 16;
var
ucal_open: function (zoneID: PUnicodeChar; len: int32_t; locale: PAnsiChar; ctype: UCalendarType; var status: UErrorCode): UCalendar; cdecl;
ucal_close: procedure (cal: UCalendar); cdecl;
ucal_getTimeZoneDisplayName: function (cal: UCalendar; dtype: UCalendarDisplayNameType; locale: PAnsiChar; result: PUnicodeChar; resultLength: int32_t;
var status: UErrorCode): int32_t; cdecl;
ucal_inDaylightTime: function (cal: UCalendar; var status: UErrorCode): UBool; cdecl;
ucal_get: function (cal: UCalendar; field: UCalendarDateFields; var status: UErrorCode): int32_t; cdecl;
var
TZStandardName: utf8string;
TZDaylightName: utf8string;
function GetIcuProc(const Name: AnsiString; var ProcPtr; libId: longint): boolean; external name 'CWSTRING_GET_ICU_PROC';
procedure ReadTimeZoneFromICU;
var
locale: utf8string;
tz: unicodestring;
res: unicodestring;
err: UErrorCode;
cal: UCalendar;
begin
if not GetIcuProc('ucal_open', ucal_open, 1) then exit;
if not GetIcuProc('ucal_close', ucal_close, 1) then exit;
if not GetIcuProc('ucal_getTimeZoneDisplayName', ucal_getTimeZoneDisplayName, 1) then exit;
if not GetIcuProc('ucal_inDaylightTime', ucal_inDaylightTime, 1) then exit;
if not GetIcuProc('ucal_get', ucal_get, 1) then exit;
locale:='en_US';
tz:=unicodestring(GetSystemProperty('persist.sys.timezone'));
err:=0;
cal:=ucal_open(PUnicodeChar(tz), Length(tz), PAnsiChar(locale), 0, err);
if cal = nil then
exit;
tzdaylight:=ucal_inDaylightTime(cal, err);
SetLength(res, 200);
SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_STANDARD, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
TZStandardName:=utf8string(res);
tzname[False]:=PAnsiChar(TZStandardName);
SetLength(res, 200);
SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_DST, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
TZDaylightName:=utf8string(res);
tzname[True]:=PAnsiChar(TZDaylightName);
Tzseconds:=ucal_get(cal, UCAL_ZONE_OFFSET, err) div 1000;
if tzdaylight then
Tzseconds:=Tzseconds + ucal_get(cal, UCAL_DST_OFFSET, err) div 1000;
ucal_close(cal);
end;
type
Ptm = ^tm;
tm = record
@ -34,10 +107,8 @@ function localtime(t: PLongInt): Ptm; cdecl; external 'c' name 'localtime';
var
c_tzname: array[0..1] of PAnsiChar; external 'c' name 'tzname';
c_timezone: longint; external 'c' name 'timezone';
c_daylignt: shortint; external 'c' name 'daylight';
procedure InitLocalTime;
procedure ReadTimeZoneFromLibC;
var
t: longint;
tt: Ptm;
@ -50,10 +121,14 @@ begin
begin
tzdaylight:=tt^.tm_isdst <> 0;
tzseconds:=tt^.tm_gmtoff;
end
else
begin
tzdaylight:=c_daylignt <> 0;
tzseconds:=-c_timezone;
end;
end;
procedure InitLocalTime;
begin
ReadTimeZoneFromLibC;
// If cuurent Android version is too old and does not support timezone
// in libc, use ICU library.
if tzname[false] = nil then
ReadTimeZoneFromICU;
end;

View File

@ -15,7 +15,11 @@
Unit Unix;
Interface
Uses BaseUnix,UnixType;
Uses
{$ifdef android}
cwstring,
{$endif android}
BaseUnix,UnixType;
// If you deprecated new symbols, please annotate the version.
// this makes it easier to decide if they can already be removed.