可定制的DST规则 [英] Customizable DST Rules

查看:266
本文介绍了可定制的DST规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么任务?

根据项目规范,我需要计算特定时区偏移的DST规则。规则无法通过 date_default_timezone_set()等标准工具应用,因为我们不能依赖软件配置,如果某些DST规则将被改变。

What's the task?
By project specification i need to calculate DST rules for specific time zone offsets. Rules cannot be applied via standard instruments like date_default_timezone_set() because we can't rely on software configuration and can't get it updated if some DST rules will be changed.

我有什么?

在DST切换日期在上周的情况下,上周是在下个月我需要递减上周的数量。现在我只有一个丑陋解决方案:

 $week = 5;
 if (
     (1 + 7 * ($week - 1)) 
     + $start['day_of_week'] 
     - date('w', mktime(0, 0, 0, $start['month'], 1, date('Y', $start['timestamp']))) 
     > 
     date('t', $start['month'])) 
 {
     $week--;
 }

我在找什么?
我正在寻找任何想法为这个最简单的解决方案,或links =)

What am i looking for?
I'm looking for any ideas for a simplest solution for this, or links =)

推荐答案

IANA官方TZ数据库存储库

它是作为源文件提供的,您可以在需要时修改它们,并重新编译成二进制文件, glibc 时间函数,因此所有使用这些时间函数的程序。如果您的发行版执行此类更新,您可能需要找到一种方法来禁用该数据库的任何自动更新,否则您将失去自定义更改。

It is available as source files that you can modify when needed and recompile into binary files that can be used by the glibc time functions, and consequently by all programs that use those time functions. You might need to find a way to disable any automatic updates to that database, if your distro performs such updates, or you will lose your custom changes.

我不是确定如果PHP实际上遵循系统范围的TZ数据库。 PECL timezonedb 程序包似乎表明它是IANA数据库的单独重新编译版本,因此可能不会观察系统范围内的更改数据库。

I'm not certain if PHP actually follows the system-wide TZ database. The PECL timezonedb package seems to indicate that it is a separate recompiled version of the IANA database, so it might not observe changes in the system-wide database.

如果PHP忽略系统范围数据库中的更改,您可以通过调用任何使用 glibc 时区感知时间函数,并且支持返回时区偏移,例如:

If PHP disregards changes in the system-wide database, you could retrieve the zone offset by invoking any external program that uses the glibc timezone-aware time functions and that supports returning the timezone offset, e.g.:

putenv('TZ=America/New_York');
$offset = exec('date +%z');

$ offset c $ c>±HHMM ,因此需要一些额外的解析。

$offset will be in format ±HHMM, so some additional parsing will be required.

您还可以找到特定时间戳的正确偏移量,当前时间:

You can also find the correct offset for specific timestamps, different from the current time:

$unix_timestamp = 1350757594;
$offset = exec('date +%z --date=@'.$unix_timestamp);

当然,通过 escapeshellarg 如果时间戳来自不受信任的源,则为必需。

Of course, proper filtering through escapeshellarg would be required if the timestamp comes from an untrusted source.

更新:这里有一个DST规则集的解决方案;没有使用外部资源

function calculate_offset($ts) {
    static $standard_offset = 2;    // = +2:00
    static $dst_offset      = 3;    // = +3:00
    static $dst_start       = 'last Sunday of March %d 1:00';
    static $dst_end         = 'last Sunday of October %d 1:00';

    date_default_timezone_set('UTC');

    $y = idate('Y', $ts);
    $start = strtotime(sprintf($dst_start, $y));
    $end = strtotime(sprintf($dst_end, $y));

    if ($start < $end) {
        // Northern hemisphere, DST starts earlier in the year than it ends
        $offset = ($ts >= $start && $ts < $end)? $dst_offset: $standard_offset;
    } else {
        // Southern hemisphere, DST ends earlier in the year than it starts
        $offset = ($ts >= $end && $ts < $start)? $standard_offset: $dst_offset;
    }
    $utc_time = strftime('%Y/%m/%d %H:%M:%S', $ts);
    $local_time = strftime('%Y/%m/%d %H:%M:%S', $ts + $offset * 60 * 60);
    printf("TS: %d; Offset: +%02d:00; UTC: %s; Local: %s\n", $ts, $offset, $utc_time, $local_time);
}

示例代码使用标准的欧洲DST规则和东欧时间补偿。您需要找到一种方式来表达您的DST开始和结束规则,其格式为 strtotime 相对格式。您的DST开始/结束规则中的%d 将被您的时间戳记所在的年份所替换,以便星期几的规则可以找到特定年份的正确日期。所有计算均以UTC时间完成,因此您的规则应参考UTC中的DST开始/结束时间。

The example code uses the standard European DST rules and Eastern European Time offsets. You will need to find a way to express your DST start and end rules in the format understood by strtotime: Relative Formats. A %d in your DST start/end rule will be replaced by the year your timestamp falls in, so that weekday-in-month rules will find correct dates for the specific year. All calculations are done in UTC times, so your rules should refer to DST start/end times in UTC.

这篇关于可定制的DST规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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