Php 如何检查时间戳是否在DST夏令时?
问题是,例如,在某些时区,秋季的2:00am或2:59am是双倍的,而在DST省时更改期间,春季不存在这种情况 如果我在一整年中每分钟都运行一个PHP循环,我如何在循环中捕捉DST的省时时间?(在当前时区中,由设置) 如何完成与PHP 5.2兼容的函数,如:Php 如何检查时间戳是否在DST夏令时?,php,dst,Php,Dst,问题是,例如,在某些时区,秋季的2:00am或2:59am是双倍的,而在DST省时更改期间,春季不存在这种情况 如果我在一整年中每分钟都运行一个PHP循环,我如何在循环中捕捉DST的省时时间?(在当前时区中,由设置) 如何完成与PHP 5.2兼容的函数,如: <?php /** returns true if a time is skipped or doubled * (for example "2013-03-10 02:30" doesen't exist in USA) *
<?php
/** returns true if a time is skipped or doubled
* (for example "2013-03-10 02:30" doesen't exist in USA)
*
* @param string $season
* @param string $datestring in the form of "2013-03-10 02:30"
* @return boolean
**/
function checkDST($datestring,$season="any"){
$tz=date_default_timezone_get();
$season=strtolower(trim($season));
if($season=="spring"){
if(/* an hour skipped */) return true;
}else if($season=="autumn"){
if(/* double hour */) return true;
} else if($season=="any") {
if(/* any of both */) return true;
}
return false
}
及
(时区见:)
编辑:
我发现了如何检测弹簧DST:
function checkDST($datestring,$season="any"){
var_dump('checking '.$datestring);
$season=strtolower(trim($season));
$datestring=substr($datestring,0,16);
if($season!="autumn" and date("Y-m-d H:i",strtotime($datestring))!=$datestring) {
return true;
}
// check for double hours in autumn
...
如果您使用PHP的date\u default\u timezone\u集来解析我假设的Unix时间戳,那么时间戳将相对于该时区进行解析。若要确定夏令时偏移(如果相关),请执行以下操作 与示例中类似的函数可能如下所示:
<?php
function checkDST($datestring, $season, $tz = "America/New_York", $minutes_from_now_to_check = 1){
$seconds_to_check = ($minutes_from_now_to_check * 60) + 30;
if (!$tz) $tz = date_default_timezone_get();
$timestamp = strtotime($datestring);
$timestamp_start = new DateTime();
$timestamp_start->setTimestamp($timestamp);
$timestamp_end = new DateTime();
$timestamp_end->setTimestamp($timestamp)->add(new DateInterval('PT'.$seconds_to_check.'S'));
$timezone = new DateTimeZone($tz);
$transitions = $timezone->getTransitions($timestamp_start->getTimestamp(), $timestamp_end->getTimestamp());
if (count($transitions) > 1) { // there's an imminent DST transition, spring or fall
if (strtolower($season) == "spring" && $transitions[1]["isdst"] === true){
return true;
}
if (strtolower($season)=="autumn" && $transitions[1]["isdst"] === false){
return true;
}
if (strtolower($season)=="any"){
return true;
}
}
return false;
}
$is_skipped = checkDST("2013-03-10 01:59","spring");
var_dump($is_skipped); // will display bool(true)
$is_skipped = checkDST("2013-03-10 12:30","spring");
var_dump($is_skipped); // will display bool(false)
$exists_two_times=checkDST("2013-11-03 01:59","autumn");
var_dump($exists_two_times); // bool(true)
$exists_two_times=checkDST("2013-11-03 03:00","autumn");
var_dump($exists_two_times); // bool(false)
这在任何时候都有效
date_default_timezone_set("America/New_York");
只有一个bug,如果我把它称为欧洲,它说现在比现在早了一个小时:
date_default_timezone_set("Europe/Berlin");
var_dump(checkDST("2013-10-27 01:30","any"));
var_dump(checkDST("2013-10-27 02:30","any"));
(欧洲的储蓄时间是从凌晨2点到凌晨3点)
这是到目前为止的结论:
<?php
/** returns true if a time is skipped or doubled
* (for example "2013-03-10 02:30" doesen't exist in USA)
*
* @param string $season "spring", "autumn", "fall" or any other string for any of the time changes
* @param string $datestring in the form of "2013-03-10 02:30"
* @return boolean
**/
function checkDST($datestring, $season, $tz = null){
$debug=true;
if($debug) echo ('checking '.$season.' '.$datestring);
$season=strtolower(trim($season));
if($season=="fall") $season="autumn";
$datestring=substr($datestring,0,16);
$monthdaystring=substr($datestring,0,10);
if(!strtotime($datestring) or date("Y-m-d",strtotime($monthdaystring))!=$monthdaystring) {
//Error
if($debug) echo "<br>Error: not a correct datestring: $datestring";
return false;
}
if($season!="autumn" and date("Y-m-d H:i",strtotime($datestring))!=$datestring) {
// spring or any
if($debug) echo "<br>".(date("Y-m-d H:i",strtotime($datestring)).'!='.$datestring);
return true;
} else if($season=="spring") {
// spring ends here
return false;
}
// "autumn" or "any"
$timestamp = strtotime($datestring);
$timestamp_start = new DateTime();
$timestamp_start->setTimestamp($timestamp);
$timestamp_end = new DateTime();
$timestamp_end->setTimestamp($timestamp)->add(new DateInterval('PT3600S'));
if (!$tz) $tz = date_default_timezone_get();
$timezone = new DateTimeZone($tz);
$transitions = $timezone->getTransitions($timestamp_start->getTimestamp(), $timestamp_end->getTimestamp());
if (count($transitions) > 1) { // there's an imminent DST transition, spring or fall
// autumn
if($debug) echo "<br>NumTransitions: ".(count($transitions));
if($debug) var_dump($transitions);
return true;
}
return false;
}
为什么时间翻倍首先是个问题?因为我想在特定的时间给药,而且患者不应该在当晚服用双倍剂量的药片,并在药片上加上一张便条:)这很有意义:)你能编辑这两个例子以包含你想要检查的特定日期字符串值吗?我刚刚编辑了我的答案,以获取一个日期字符串,并可以选择使用日期\默认\时区\集
。我还将检查的时间间隔更改为31分钟(而不是之前的一小时),以便它与您描述的30分钟时间间隔数组更精确地关联。以何种方式strotime
返回2:30?当我使用php内置的EST时区将其输入到一个DateTime
类中时,我得到:“2013-03-10 01:30:00”
…据我所知,夏令时转换发生在凌晨1:59=>3:00(至少在春季),有一些错误:检查DST(“2013-03-10 01:58”,“春季”)代码>返回错误我认为你的方法不起作用。更好的方法是从输入日期字符串创建一个时间戳,并将其转换回日期字符串“Y-m-dh:i”,然后比较是否发生了更改。因为初始的strotime
已经显示,输入时间不存在。它以什么方式不工作?你运行代码并看到结果了吗?我的方法检查当前分钟,看看夏令时是否在下一分钟发生。这满足了您原来的问题,但您已经多次更改了问题。如果它不起作用,而你有更好或不同的方法,你应该发布它。
date_default_timezone_set("Europe/Berlin");
var_dump(checkDST("2013-10-27 01:30","any"));
var_dump(checkDST("2013-10-27 02:30","any"));
<?php
/** returns true if a time is skipped or doubled
* (for example "2013-03-10 02:30" doesen't exist in USA)
*
* @param string $season "spring", "autumn", "fall" or any other string for any of the time changes
* @param string $datestring in the form of "2013-03-10 02:30"
* @return boolean
**/
function checkDST($datestring, $season, $tz = null){
$debug=true;
if($debug) echo ('checking '.$season.' '.$datestring);
$season=strtolower(trim($season));
if($season=="fall") $season="autumn";
$datestring=substr($datestring,0,16);
$monthdaystring=substr($datestring,0,10);
if(!strtotime($datestring) or date("Y-m-d",strtotime($monthdaystring))!=$monthdaystring) {
//Error
if($debug) echo "<br>Error: not a correct datestring: $datestring";
return false;
}
if($season!="autumn" and date("Y-m-d H:i",strtotime($datestring))!=$datestring) {
// spring or any
if($debug) echo "<br>".(date("Y-m-d H:i",strtotime($datestring)).'!='.$datestring);
return true;
} else if($season=="spring") {
// spring ends here
return false;
}
// "autumn" or "any"
$timestamp = strtotime($datestring);
$timestamp_start = new DateTime();
$timestamp_start->setTimestamp($timestamp);
$timestamp_end = new DateTime();
$timestamp_end->setTimestamp($timestamp)->add(new DateInterval('PT3600S'));
if (!$tz) $tz = date_default_timezone_get();
$timezone = new DateTimeZone($tz);
$transitions = $timezone->getTransitions($timestamp_start->getTimestamp(), $timestamp_end->getTimestamp());
if (count($transitions) > 1) { // there's an imminent DST transition, spring or fall
// autumn
if($debug) echo "<br>NumTransitions: ".(count($transitions));
if($debug) var_dump($transitions);
return true;
}
return false;
}