sub
Methods
{
return
qw( FromEnv
FromEtcLocaltime
FromEtcTimezone
FromEtcTIMEZONE
FromEtcSysconfigClock
FromEtcDefaultInit
)
;
}
sub
EnvVars {
return
'TZ'
}
sub
FromEtcLocaltime
{
my
$class
=
shift
;
my
$lt_file
=
'/etc/localtime'
;
return
unless
-r
$lt_file
&& -s _;
my
$real_name
;
if
( -l
$lt_file
)
{
$real_name
=
$class
->_Readlink(
$lt_file
);
}
$real_name
||=
$class
->_FindMatchingZoneinfoFile(
$lt_file
);
if
(
defined
$real_name
)
{
my
(
$vol
,
$dirs
,
$file
) = File::Spec->splitpath(
$real_name
);
my
@parts
=
grep
{
defined
&&
length
} File::Spec->splitdir(
$dirs
),
$file
;
foreach
my
$x
(
reverse
0..
$#parts
)
{
my
$name
=
(
$x
<
$#parts
?
join
'/'
,
@parts
[
$x
..
$#parts
] :
$parts
[
$x
]
);
my
$tz
;
{
local
$@;
$tz
=
eval
{ DateTimeX::Lite::TimeZone->load(
name
=>
$name
) };
}
return
$tz
if
$tz
;
}
}
}
sub
_Readlink
{
my
$link
=
$_
[1];
return
Cwd::abs_path(
$link
);
}
sub
_FindMatchingZoneinfoFile
{
my
$class
=
shift
;
my
$file_to_match
=
shift
;
return
unless
-d
'/usr/share/zoneinfo'
;
my
$size
= -s
$file_to_match
;
my
$real_name
;
local
$@;
local
$_
;
eval
{
local
$SIG
{__DIE__};
File::Find::find
( {
wanted
=>
sub
{
if
( !
defined
$real_name
&& -f
$_
&& ! -l
$_
&&
$size
== -s _
&& File::Basename::basename(
$_
) ne
'posixrules'
&& File::Compare::compare(
$_
,
$file_to_match
) == 0
)
{
$real_name
=
$_
;
die
{
found
=> 1 };
}
},
no_chdir
=> 1,
},
'/usr/share/zoneinfo'
,
);
};
if
($@)
{
return
$real_name
if
ref
$@ && $@->{found};
die
$@;
}
}
sub
FromEtcTimezone
{
my
$class
=
shift
;
my
$tz_file
=
'/etc/timezone'
;
return
unless
-f
$tz_file
&& -r _;
local
*TZ
;
open
TZ,
"<$tz_file"
or
die
"Cannot read $tz_file: $!"
;
my
$name
=
join
''
, <TZ>;
close
TZ;
$name
=~ s/^\s+|\s+$//g;
return
unless
$class
->_IsValidName(
$name
);
local
$@;
return
eval
{ DateTimeX::Lite::TimeZone->load(
name
=>
$name
) };
}
sub
FromEtcTIMEZONE
{
my
$class
=
shift
;
my
$tz_file
=
'/etc/TIMEZONE'
;
return
unless
-f
$tz_file
&& -r _;
local
*TZ
;
open
TZ,
"<$tz_file"
or
die
"Cannot read $tz_file: $!"
;
my
$name
;
while
(
defined
(
$name
= <TZ> ) )
{
if
(
$name
=~ /\A\s
*TZ
\s*=\s*(\S+)/ )
{
$name
= $1;
last
;
}
}
close
TZ;
return
unless
$class
->_IsValidName(
$name
);
local
$@;
return
eval
{ DateTimeX::Lite::TimeZone->load(
name
=>
$name
) };
}
sub
FromEtcSysconfigClock
{
my
$class
=
shift
;
return
unless
-r
"/etc/sysconfig/clock"
&& -f _;
my
$name
=
$class
->_ReadEtcSysconfigClock();
return
unless
$class
->_IsValidName(
$name
);
local
$@;
return
eval
{ DateTimeX::Lite::TimeZone->load(
name
=>
$name
) };
}
sub
_ReadEtcSysconfigClock
{
my
$class
=
shift
;
local
*CLOCK
;
open
CLOCK,
'</etc/sysconfig/clock'
or
die
"Cannot read /etc/sysconfig/clock: $!"
;
local
$_
;
while
(<CLOCK>)
{
return
$1
if
/^(?:TIME)?ZONE=
"([^"
]+)"/;
}
}
sub
FromEtcDefaultInit
{
my
$class
=
shift
;
return
unless
-r
"/etc/default/init"
&& -f _;
my
$name
=
$class
->_ReadEtcDefaultInit();
return
unless
$class
->_IsValidName(
$name
);
local
$@;
return
eval
{ DateTimeX::Lite::TimeZone->load(
name
=>
$name
) };
}
sub
_ReadEtcDefaultInit
{
my
$class
=
shift
;
local
*INIT
;
open
INIT,
'</etc/default/init'
or
die
"Cannot read /etc/default/init: $!"
;
local
$_
;
while
(<INIT>)
{
return
$1
if
/^TZ=(.+)/;
}
}
1;