WeBid:夏令时的时区计算不正确 [英] WeBid: Timezones with daylight savings time not calculated correctly

查看:95
本文介绍了WeBid:夏令时的时区计算不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前正在使用一个开源应用程序:WeBid(在此处可用)

I'm currently using an open source application: WeBid (available here)

这里是问题所在:


  • 用户在数据库中存储了首选时区

  • 该站点具有存储在数据库中的默认时区

  • 所有数据库存储的日期均存储在 GMT-0处

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

The application doesn't calculate the DST (Daylight Savings Time) correctly as it uses the following code:

(包括/ functions_global.php)

(includes/functions_global.php)

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

gtpotyf解释:

gtpotyf explains:


gmdate('I')->如果DST处于活动状态,则返回1;否则,返回0。但是,由于gmdate始终使用GMT(+0)且该时区没有DST,因此
始终会返回0。

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.

使用date('I ')代替gmdate('I')会更好,但是
仍然不正确,因为它使用服务器时区,而
仍不使用用户时区。

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的最新版本未进行最终更正,请帮助我解决此问题。

No final correction was adopted by WeBid's latest version, please help me resolve this issue.

来源

推荐答案

为了正确地区分时区,您需要做很多事情。

In order to sort out timezones properly you'll need to do a number of things.

将服务器设置为UTC,以便PHP的时间 date 函数返回UTC。时间戳记。 (除了相关的功能,例如 strftime

Set your server to UTC, so that PHP's time and date functions return a UTC timestamp. (In addition to associated functions such as strftime.

根据您的数据库,您可以将其时区设置为UTC。 MySQL的相关文档位于此处

Depending on your database, you can set its timezone to UTC as well. MySQL's documentation on the subject is here.

您还需要将其中存储的日期时间迁移到UTC(我不知道您所说的GMT-0是什么意思) 。)

You'll need to migrate the datetimes stored in there to UTC if they aren't already. (I'm not sure what you mean by GMT-0.)

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

Let users choose a timezone in the format 'Europe/London' as supported by PHP's DateTimeZone class.

经过一些研究,我将以下时区组合在一起放在下拉框中显示给用户,因为我不想重复(例如,阿姆斯特丹和布鲁塞尔在同一时区。)我不会主张

Following some research, I put together the following array of timezones to present to users in a drop down box, as I didn't want duplicates (Amsterdam and Brussels are in the same timezone, for example.) I wouldn't claim it to be perfect though. Depending on your user base you may want to investigate certain timezones in more detail.

$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转换为用户的时区

When dates come out of your database, they'll need to be converted from UTC into the user's timezone.

$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应用程序并修改相应的部分才能正确转换

You'll need to go through the WeBid application and modify the appropriate parts to convert properly.

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

So, using the above code, you'll need a couple of functions that do something like this:

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);

这篇关于WeBid:夏令时的时区计算不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆