php - WeBid : Timezones with daylight savings time not calculated correctly

标签 php timezone dst

我目前正在使用一个开源应用程序:WeBid(可用 here)

问题是:

  • 用户在数据库中存储了首选时区
  • 该站点在数据库中存储了一个默认时区
  • 所有数据库存储的日期都存储在“GMT-0”

应用程序无法正确计算 DST(夏令时),因为它使用了以下代码:

(包括/functions_global.php)

$this->ctime = time() + (($this->SETTINGS['timecorrection'] + gmdate('I')) * 3600);
$this->tdiff = ($this->SETTINGS['timecorrection'] + gmdate('I')) * 3600;

gtpotyf 解释说:

gmdate('I') -> Returns 1 if DST is active, 0 if not active. However since gmdate always uses GMT(+0) and that timezone has no DST it will always return 0.

using date('I') instead of gmdate('I') would work better, but would still not be correct since it uses the timezone from the server and still not the users timezone.

WeBid最新版本未采用最终修正,请帮我解决这个问题。

Source

最佳答案

为了正确地整理时区,您需要做一些事情。

将您的服务器设置为 UTC,以便 PHP 的 timedate 函数返回 UTC 时间戳。 (除了 strftime 等相关函数。

根据您的数据库,您也可以将其时区设置为 UTC。 MySQL 关于这个主题的文档是 here .

您需要将存储在其中的日期时间迁移到 UTC(如果尚未迁移)。 (我不确定你所说的 GMT-0 是什么意思。)

让用户选择 PHP 的 DateTimeZone 类支持的“欧洲/伦敦”格式的时区。

经过一些研究,我将以下时区数组组合在一起,在下拉框中呈现给用户,因为我不想重复(例如,阿姆斯特丹和布鲁塞尔位于同一时区。)我不会声称它是完美的。根据您的用户群,您可能想要更详细地调查某些时区。

$timezones = array(
        'Pacific/Midway' => '(UTC-11:00) Midway Island, Samoa',
        'Pacific/Honolulu' => '(UTC-10:00) Hawaii-Aleutian',
        'Pacific/Marquesas' => '(UTC-09:30) Marquesas Islands',
        'Pacific/Gambier' => '(UTC-09:00) Gambier Islands',
        'America/Anchorage' => '(UTC-09:00) Alaska',
        'America/Ensenada' => '(UTC-08:00) Tijuana, Baja California',
        'Etc/GMT+8' => '(UTC-08:00) Pitcairn Islands',
        'America/Los_Angeles' => '(UTC-08:00) Pacific Time (US & Canada)',
        'America/Denver' => '(UTC-07:00) Mountain Time (US & Canada)',
        'America/Chihuahua' => '(UTC-07:00) Chihuahua, La Paz, Mazatlan',
        'America/Dawson_Creek' => '(UTC-07:00) Arizona',
        'America/Belize' => '(UTC-06:00) Saskatchewan, Central America',
        'America/Cancun' => '(UTC-06:00) Guadalajara, Mexico City, Monterrey',
        'Chile/EasterIsland' => '(UTC-06:00) Easter Island',
        'America/Chicago' => '(UTC-06:00) Central Time (US & Canada)',
        'America/New_York' => '(UTC-05:00) Eastern Time (US & Canada)',
        'America/Havana' => '(UTC-05:00) Cuba',
        'America/Bogota' => '(UTC-05:00) Bogota, Lima, Quito, Rio Branco',
        'America/Caracas' => '(UTC-04:30) Caracas',
        'America/Santiago' => '(UTC-04:00) Santiago',
        'America/La_Paz' => '(UTC-04:00) La Paz',
        'Atlantic/Stanley' => '(UTC-04:00) Falkland Islands',
        'America/Campo_Grande' => '(UTC-04:00) Brazil',
        'America/Goose_Bay' => '(UTC-04:00) Atlantic Time (Goose Bay)',
        'America/Glace_Bay' => '(UTC-04:00) Atlantic Time (Canada)',
        'America/St_Johns' => '(UTC-03:30) Newfoundland',
        'America/Araguaina' => '(UTC-03:00) UTC-3',
        'America/Montevideo' => '(UTC-03:00) Montevideo',
        'America/Miquelon' => '(UTC-03:00) Miquelon, St. Pierre',
        'America/Godthab' => '(UTC-03:00) Greenland',
        'America/Argentina/Buenos_Aires' => '(UTC-03:00) Buenos Aires',
        'America/Sao_Paulo' => '(UTC-03:00) Brasilia',
        'America/Noronha' => '(UTC-02:00) Mid-Atlantic',
        'Atlantic/Cape_Verde' => '(UTC-01:00) Cape Verde Is.',
        'Atlantic/Azores' => '(UTC-01:00) Azores',
        'Europe/Dublin' => '(UTC) Irish Standard Time : Dublin',
        'Europe/Lisbon' => '(UTC) Western European Time : Lisbon',
        'Europe/London' => '(GMT) Greenwich Mean Time : London, Belfast',
        'Africa/Abidjan' => '(GMT) Monrovia, Reykjavik',
        'Europe/Amsterdam' => '(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna',
        'Europe/Belgrade' => '(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague',
        'Europe/Brussels' => '(UTC+01:00) Brussels, Copenhagen, Madrid, Paris',
        'Africa/Algiers' => '(UTC+01:00) West Central Africa',
        'Africa/Windhoek' => '(UTC+01:00) Windhoek',
        'Asia/Beirut' => '(UTC+02:00) Beirut',
        'Africa/Cairo' => '(UTC+02:00) Cairo',
        'Asia/Gaza' => '(UTC+02:00) Gaza',
        'Africa/Johannesburg' => '(UTC+02:00) Johannesburg, Harare, Pretoria',
        'Asia/Jerusalem' => '(UTC+02:00) Jerusalem',
        'Europe/Athens' => '(UTC+02:00) Athens',
        'Europe/Minsk' => '(UTC+02:00) Minsk',
        'Asia/Damascus' => '(UTC+02:00) Syria',
        'Europe/Moscow' => '(UTC+03:00) Moscow, St. Petersburg, Volgograd',
        'Africa/Addis_Ababa' => '(UTC+03:00) Nairobi',
        'Asia/Tehran' => '(UTC+03:30) Tehran',
        'Asia/Dubai' => '(UTC+04:00) Abu Dhabi, Muscat',
        'Asia/Yerevan' => '(UTC+04:00) Yerevan',
        'Asia/Kabul' => '(UTC+04:30) Kabul',
        'Asia/Yekaterinburg' => '(UTC+05:00) Ekaterinburg',
        'Asia/Tashkent' => '(UTC+05:00) Tashkent',
        'Asia/Kolkata' => '(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi',
        'Asia/Katmandu' => '(UTC+05:45) Kathmandu',
        'Asia/Dhaka' => '(UTC+06:00) Astana, Dhaka',
        'Asia/Novosibirsk' => '(UTC+06:00) Novosibirsk',
        'Asia/Rangoon' => '(UTC+06:30) Yangon (Rangoon)',
        'Asia/Bangkok' => '(UTC+07:00) Bangkok, Hanoi, Jakarta',
        'Asia/Krasnoyarsk' => '(UTC+07:00) Krasnoyarsk',
        'Asia/Hong_Kong' => '(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi',
        'Asia/Irkutsk' => '(UTC+08:00) Irkutsk, Ulaan Bataar',
        'Australia/Perth' => '(UTC+08:00) Perth',
        'Australia/Eucla' => '(UTC+08:45) Eucla',
        'Asia/Tokyo' => '(UTC+09:00) Osaka, Sapporo, Tokyo',
        'Asia/Seoul' => '(UTC+09:00) Seoul',
        'Asia/Yakutsk' => '(UTC+09:00) Yakutsk',
        'Australia/Adelaide' => '(UTC+09:30) Adelaide',
        'Australia/Darwin' => '(UTC+09:30) Darwin',
        'Australia/Sydney' => '(UTC+10:00) Sydney, Canberra, Brisbane',
        'Australia/Hobart' => '(UTC+10:00) Hobart',
        'Asia/Vladivostok' => '(UTC+10:00) Vladivostok',
        'Australia/Lord_Howe' => '(UTC+10:30) Lord Howe Island',
        'Etc/GMT-11' => '(UTC+11:00) Solomon Is., New Caledonia',
        'Asia/Magadan' => '(UTC+11:00) Magadan',
        'Pacific/Norfolk' => '(UTC+11:30) Norfolk Island',
        'Asia/Anadyr' => '(UTC+12:00) Anadyr, Kamchatka',
        'Pacific/Auckland' => '(UTC+12:00) Auckland, Wellington',
        'Etc/GMT-12' => '(UTC+12:00) Fiji, Kamchatka, Marshall Is.',
        'Pacific/Chatham' => '(UTC+12:45) Chatham Islands',
        'Pacific/Tongatapu' => '(UTC+13:00) Nuku Alofa',
        'Pacific/Kiritimati' => '(UTC+14:00) Kiritimati'
    );

当日期从您的数据库中出来时,需要将它们从 UTC 转换为用户的时区。

$timestamp = time(); // or a timestamp from your DB

# create server and user timezone objects
$fromZone = new DateTimeZone('UTC'); // UTC
$toZone = new DateTimeZone($userTimezone); // Europe/London, or whatever it happens to be

$time = date('Y-m-d H:i:s', $timestamp);
$dt = new DateTime($time, $fromZone);
echo $dt->format('Y-m-d H:i:s'); // Still UTC

$dt->setTimezone($toZone);
echo $dt->format('Y-m-d H:i:s'); // Converted

您需要浏览 WeBid 应用程序并修改适当的部分以正确转换。


因此,使用上面的代码,您需要一些函数来执行以下操作:

function getConvertedDateTimeObject($timestamp, $userTimezone){
    # create server and user timezone objects
    $fromZone = new DateTimeZone('UTC'); // UTC
    $toZone = new DateTimeZone($userTimezone); // Europe/London, or whatever it happens to be

    $time = date('Y-m-d H:i:s', $timestamp);
    $dt = new DateTime($time, $fromZone);
    $dt->setTimezone($toZone);
    return $dt;
}

function getUserTimestamp($timestamp, $userTimezone){
    $dt = getConvertedDateTimeObject($timestamp, $userTimezone);
    return $dt->getTimestamp();
}

function getUserOffset($timestamp, $userTimezone){
    $dt = getConvertedDateTimeObject($timestamp, $userTimezone);
    return $dt->getOffset();
}

然后在你的类里面:

$this->ctime = getUserTimestamp(time(), $userTimezone); // I assume you have access to the user's timezone?
$this->tdiff = getUserOffset(time(), $userTimezone);

关于php - WeBid : Timezones with daylight savings time not calculated correctly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11890894/

相关文章:

php - 从数据库中选择所有以小写字母开头的字符串

javascript - 不同浏览器上的不同行为

python - 从 Django 的 make_aware 解决 AmbiguousTimeError

php - 从 Metabox 调用 WordPress Gallery uploader /选择器

php - 将收到的电子邮件保存到数据库

php - 试图找到一种简单的方法让 PHP 和 Mysql DB 为 PHP5.5 做数学运算(AVG MIN MAX)

javascript - 将 Javascript 日期转换为带有时区信息的 UTC

c# - 如何使用 C#/.NET 将日期时间转换为时间戳(忽略当前时区)

java - 根据用户时区进行日期转换

c# - 边际时间的夏令时更改时间表触发器