function get($base, $opts=array())
{
- self::getOffsets();
+ $this->lang = !empty($_REQUEST['lang']) && in_array($_REQUEST['lang'], array('en', 'zh_CN')) ? $_REQUEST['lang'] : 'en';
+ self::getTimezones($this->lang);
$data = array();
- foreach(self::$offsets as $tz => $o) {
- $arr = explode('/', $tz);
+ foreach(self::$timezones as $tz => $o) {
+ if(!empty($_REQUEST['region']) && $_REQUEST['region'] != $o['region']) {
+ continue;
+ }
- if(!empty($_REQUEST['region']) && $_REQUEST['region'] != $arr[0]) {
+ if(
+ !empty($_REQUEST['query']['area_start'])
+ &&
+ substr(strtolower($o['area']), 0, strlen($_REQUEST['query']['area_start'])) != strtolower($_REQUEST['query']['area_start'])
+ ){
continue;
}
$data[] = array(
- 'region' => $arr[0],
- 'area' => $arr[1],
- 'offset' => $o,
- 'displayArea' => self::getDisplayArea($tz)
+ 'region' => $o['region'],
+ 'area' => $o['area'],
+ 'displayRegion' => $o['displayRegion'],
+ 'displayArea' => $o['displayArea']
);
}
'fields' => array(
'region',
'area',
- 'offset',
+ 'displayRegion',
'displayArea'
)
),
die('Invalid post');
}
- static $offsets = array();
+ static $timezones = array();
- static function getOffsets()
+ static function getTimezones($lang)
{
- if(!empty(self::$offsets)) {
- return self::$offsets;
+ if(!empty(self::$timezones)) {
+ return self::$timezones;
}
-
- $ce = DB_DataObject::factory('core_enum');
- $ce->query('
+ $ce = DB_DataObject::factory('core_enum');
+ $ce->query("
SELECT
- *, TIME_FORMAT(TIMEDIFF(NOW(), CONVERT_TZ(NOW(), Name, "UTC")), "%H:%i") as offset
+ *, TIME_FORMAT(TIMEDIFF(NOW(), CONVERT_TZ(NOW(), Name, 'UTC')), '%H:%i') as timeOffset
FROM
mysql.time_zone_name
+ WHERE
+ Name LIKE '%/%'
+ AND
+ Name NOT LIKE '%/%/%'
+ AND
+ Name NOT LIKE 'right%'
+ AND
+ Name NOT LIKE 'posix%'
+ AND
+ Name NOT LIKE 'Etc%'
ORDER BY
- offset DESC,
- Name DESC
- ');
+ SUBSTRING_INDEX(Name, '/', 1) ASC,
+ timeoffset ASC,
+ Name ASC
+ ");
- while($ce->fetch()) {
- // ignroe timezone such as 'CET' and 'America/Argentina/Buenos_Aires'
- if(substr_count($ce->Name, '/') != 1) {
+ $regions = DB_DataObject::factory('core_enum');
+ $regions->setFrom(array(
+ 'etype' => 'Timezone.Region',
+ 'active' => 1
+ ));
+ $regionIds = $regions->fetchAll('display_name', 'id');
+
+ $areas = DB_DataObject::factory('core_enum');
+ $areas->setFrom(array(
+ 'etype' => 'Timezone.Area',
+ 'active' => 1
+ ));
+ $areaIds = $areas->fetchAll('display_name', 'id');
+
+
+ $ct = DB_DataObject::factory('core_templatestr');
+ $ct->lang = $lang;
+ $ct->on_table = 'core_enum';
+ $ct->active = 1;
+ $translations = array();
+ foreach($ct->fetchAll() as $t) {
+ if(empty($t->txt)) {
continue;
}
+ $translations[$t->on_id][$t->on_col] = $t->txt;
+ }
+
+ while($ce->fetch()) {
+ // ignroe timezone such as 'CET' and 'America/Argentina/Buenos_Aires'
+
$ar = explode('/', $ce->Name);
// ignore timezone such as 'Etc/GMT+8'
- if($ar[0] == 'Etc') {
- continue;
+
+ $region = $displayRegion = $ar[0];
+
+ if(!empty($translations[$regionIds[$region]]['display_name'])) {
+ $displayRegion = $translations[$regionIds[$region]]['display_name'];
}
- self::$offsets[$ce->Name] = substr($ce->offset, 0, 1) == '-' ? $ce->offset : '+' . $ce->offset;
+ $area = $ar[1];
+ $displayArea = str_replace('_', ' ', $area);
+
+ if(!empty($translations[$areaIds[$displayArea]]['display_name'])) {
+ $displayArea = $translations[$areaIds[$displayArea]]['display_name'];
+ }
+
+ $timeOffset = ((substr($ce->timeOffset, 0, 1) == '-') ? '' : '+') . $ce->timeOffset;
+ $displayOffset = '(GMT ' . $timeOffset . ')';
+
+ self::$timezones[$ce->Name] = array(
+ 'region' => $region,
+ 'area' => $area,
+ 'displayName' => $ar[0] . '/' . $displayArea . ' ' . $displayOffset,
+ 'displayRegion' => $displayRegion,
+ 'displayArea' => $displayArea . ' ' . $displayOffset
+ );
}
- return self::$offsets;
+ return self::$timezones;
}
- static function getDisplayArea($timezone)
+ static function isValidTimeZone($tz) {
+ try {
+ new DateTimeZone($tz);
+ }
+ catch (Exception $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ static function toRegion($tz)
{
- self::getOffsets();
+ if(!self::isValidTimeZone($tz)) {
+ return '';
+ }
+
+ return explode('/', $tz)[0];
+ }
- // invalid timezone
- if(!isset(self::$offsets[$timezone])) {
+ static function toArea($tz)
+ {
+ if(!self::isValidTimeZone($tz)) {
return '';
}
- $ar = explode('/', $timezone);
+ return explode('/', $tz)[1];
+ }
+
+ static function toTimeOffset($dt, $tz)
+ {
+ if(!self::isValidTimeZone($tz)) {
+ return '';
+ }
- // e.g. 'Hong_Kong (GMT +08:00)'
- return $ar[1] . ' (GMT ' . self::$offsets[$timezone] . ')';
+ if($dt == '0000-00-00 00:00:00' || $dt == '') {
+ $dt = 'NOW';
+ }
+
+ $date = new DateTime($dt, new DateTimeZone($tz));
+ return $date->format('P');
}
-
+ static function toDisplayRegion($lang, $tz)
+ {
+ $region = explode('/', $tz)[0];
+
+ $ce = DB_DataObject::factory('core_enum');
+ $ce->setFrom(array(
+ 'etype' => 'Timezone.Region',
+ 'active' => 1,
+ 'name' => $region,
+ 'display_name' => $region
+ ));
+ if(!$ce->find(true)) {
+ return $region;
+ }
+
+ $ct = DB_DataObject::factory('core_templatestr');
+ $ct->setFrom(array(
+ 'lang' => $lang,
+ 'on_table' => 'core_enum',
+ 'on_id' => $ce->id,
+ 'on_col' => 'display_name',
+ 'active' => 1
+ ));
+ if(!$ct->find(true) || empty($ct->txt)) {
+ return $region;
+ }
+ return $ct->txt;
+ }
+
+ static function toDisplayArea($lang, $dt, $tz)
+ {
+ $displayArea = str_replace('_', ' ', self::toArea($tz));
+ $displayOffset = '(GMT ' . self::toTimeOffset($dt,$tz) . ')';
+
+ $ce = DB_DataObject::factory('core_enum');
+ $ce->setFrom(array(
+ 'etype' => 'Timezone.Area',
+ 'active' => 1,
+ 'name' => $displayArea,
+ 'display_name' => $displayArea
+ ));
+
+ if(!$ce->find(true)) {
+ return $displayArea . ' ' . $displayOffset;
+ }
+
+ $ct = DB_DataObject::factory('core_templatestr');
+ $ct->setFrom(array(
+ 'lang' => $lang,
+ 'on_table' => 'core_enum',
+ 'on_id' => $ce->id,
+ 'on_col' => 'display_name',
+ 'active' => 1
+ ));
+ if(!$ct->find(true) || empty($ct->txt)) {
+ return $displayArea . ' ' . $displayOffset;
+ }
+
+ return $ct->txt . ' ' . $displayOffset;
+
+ }
+
+ static function toDisplayName($lang, $dt, $tz)
+ {
+ return self::toDisplayRegion($lang, $tz) . '/' . self::toDisplayArea($lang, $dt, $tz);
+ }
}
\ No newline at end of file