WeBid:夏时制时区计算不正确

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

这是问题:

  • 用户具有存储在数据库中的首选时区
  • 该站点具有存储在数据库中的默认时区
  • 所有分贝存储日期都存储在“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') - >如果DST处于活动状态,则返回1,否则返回0。 但由于gmdate总是使用GMT(+0),并且该时区没有DST,它将始终返回0。

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

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

    资源


    为了正确地理清时区,你需要做很多事情。

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

    根据您的数据库,您可以将其时区设置为UTC。 关于这个主题的MySQL文档就在这里。

    如果尚未存储在那里的日期时间需要迁移到UTC。 (我不确定你的意思是GMT-0。)

    让用户选择由PHP的DateTimeZone类支持的'Europe / London'格式的时区。

    经过一番研究,我将下面的一组时区放在一个下拉框中向用户展示,因为我不想重复(例如,阿姆斯特丹和布鲁塞尔在同一时区)。我不会声称它是虽然完美。 根据您的用户群,您可能需要更详细地调查某些时区。

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

    bcmcfc的答案的替代解决方案(几乎可以说这一切):

    从WeBid中删除任何时区支持(至少禁用任何定制),并将所有内容保存为UTC(如果尚未)。

    修改界面以使用Javascript显示日期和时间戳。 浏览器将根据浏览器或操作系统的设置,正确地转换unix时间戳(不要忘记乘以1000,Javascript的Date需要毫秒,而不是PHP中的秒数)。

    例如,不是输出2012-08-18 09:33:43,而是输出<script>document.write(new Date(1345282423*1000).toString());</script> ,其中1345282423直接获得从数据库,或使用strtotime

    您只需更改显示日期和时间戳的功能,并禁用时区自定义(强制UTC / GMT)(不要忘记date_default_timezone_set("UTC"); )。

    这对我来说似乎微不足道。

    链接地址: http://www.djcxy.com/p/29363.html

    上一篇: WeBid: Timezones with daylight savings time not calculated correctly

    下一篇: How to tackle daylight savings using TimeZone in Java