ber*_*kes 27 php date iso8601 intervals
我正在使用的库和Web服务以ISO 8601格式PnYnMnDTnHnMnS传送时间间隔:.我想将这些格式转换为秒.反之亦然.使用秒数更容易计算.
示例间隔值为:
我需要两个函数:从这些值解析为秒:iso8601_interval_to_seconds()以及从秒到这样的间隔:iso8601_interval_from_seconds().
后者相当简单,因为它可以作为"PT {$ seconds} S"完成,只需要在几秒钟内完成.也许这可以通过切换到H(小时)或M(分钟)的解析器更好地完成?
第一个更难,但也许有一个技巧与PHP中的许多字符串到今天的转换器之一?我很想学习如何使用这样的函数来解析间隔.或者学习另一种选择.
Fan*_*nis 18
看起来PHP 5.3的DateInterval支持这一点.
如果你不能使用5.3,我想任何这样的转换函数都会知道一年,一个月,一天,一小时和一分钟的秒数.然后,当从秒转换时,它将按此顺序分割,每次取前一操作的模数,直到仅剩下<60秒.从ISO 8601间隔表示转换时,解析字符串并相应地乘以每个找到的元素应该是微不足道的.
小智 8
strtotime不能直接使用ISO 8601格式(例如P1Y1DT1S),但它理解的格式(1Year1Day1Second)并不太远 - 这将是一个非常直接的转换.(有点"hacky"......但那是你的PHP).
谢谢李,我不知道strtotime接受了这种格式.这是我拼图中缺失的一部分.也许我的功能可以完成你的答案.
function parse_duration($iso_duration, $allow_negative = true){
// Parse duration parts
$matches = array();
preg_match('/^(-|)?P([0-9]+Y|)?([0-9]+M|)?([0-9]+D|)?T?([0-9]+H|)?([0-9]+M|)?([0-9]+S|)?$/', $iso_duration, $matches);
if(!empty($matches)){
// Strip all but digits and -
foreach($matches as &$match){
$match = preg_replace('/((?!([0-9]|-)).)*/', '', $match);
}
// Fetch min/plus symbol
$result['symbol'] = ($matches[1] == '-') ? $matches[1] : '+'; // May be needed for actions outside this function.
// Fetch duration parts
$m = ($allow_negative) ? $matches[1] : '';
$result['year'] = intval($m.$matches[2]);
$result['month'] = intval($m.$matches[3]);
$result['day'] = intval($m.$matches[4]);
$result['hour'] = intval($m.$matches[5]);
$result['minute'] = intval($m.$matches[6]);
$result['second'] = intval($m.$matches[7]);
return $result;
}
else{
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
该功能还支持负面格式. -P10Y9MT7M5S将返回如下数组: [year] => -10 [month] => -9 [day] => 0 [小时] => 0 [分钟] => -7 [秒] => -5如果这样不希望行为作为第二个参数传递false.这样,函数将始终返回正值.min/plus符号仍将在结果键['symbol']中可用.
并稍加更新:此函数使用第一个函数来获取总秒数.
function get_duration_seconds($iso_duration){
// Get duration parts
$duration = parse_duration($iso_duration, false);
if($duration){
extract($duration);
$dparam = $symbol; // plus/min symbol
$dparam .= (!empty($year)) ? $year . 'Year' : '';
$dparam .= (!empty($month)) ? $month . 'Month' : '';
$dparam .= (!empty($day)) ? $day . 'Day' : '';
$dparam .= (!empty($hour)) ? $hour . 'Hour' : '';
$dparam .= (!empty($minute)) ? $minute . 'Minute' : '';
$dparam .= (!empty($second)) ? $second . 'Second' : '';
$date = '19700101UTC';
return strtotime($date.$dparam) - strtotime($date);
}
else{
// Not a valid iso duration
return false;
}
}
$foo = '-P1DT1S';
echo get_duration_seconds($foo); // Output -86399
$bar = 'P1DT1S';
echo get_duration_seconds($bar); // Output 86401
Run Code Online (Sandbox Code Playgroud)
请注意,如果不知道实际的开始日期/时间,则无法准确地将包含天,月和/或年的持续时间转换为持续时间(如秒).
例如
1 SEP 2010: +P1M2D means +2764800 seconds
1 OCT 2010: +P1M2D means +2851200 seconds
Run Code Online (Sandbox Code Playgroud)
那是因为9月有30天,10月有31天.转换年间隔时会出现同样的问题,因为闰年和闰秒.闰年也为月转换带来了进一步的复杂性 - 因为2月比闰年更长一天.在实行夏令时的区域中,天数是有问题的 - 在DST过渡期间发生的一天时间实际上比其他时间长1小时.
所有这一切 - 当然,您可以将仅包含小时,分钟和秒的值压缩为仅包含秒的值.我建议你构建一个简单的解析器来完成这项工作(或者考虑一个正则表达式).
请注意上面提到的陷阱 - 有龙.如果您打算处理Days,Months和/或Years,则需要使用其中一种内置机制在已知日期/时间的上下文中为您进行数学运算.正如其他人所提到的:DateInterval类与DateTime类提供的函数组合可能是解决此问题的最直观方式.但这仅适用于PHP 5.3.0或更高版本.
如果你必须使用低于v5.3.0,你可以尝试围绕这个小宝石构建一些东西:
$startDateTime = '19700101UTC';
$duration = strtotime( $startDateTime.'+1Year1Day1Second' ) - strtotime($startDateTime);
print("Duration in Seconds: $duration");
Run Code Online (Sandbox Code Playgroud)
strtotime不会直接与ISO 8601格式的工作(例如P1Y1DT1S),但它的格式不理解(1Year1Day1Second)是不是太远了-它会一个非常直接的转换.(有点"hacky"......但那是你的PHP).
祝好运!
| 归档时间: |
|
| 查看次数: |
34957 次 |
| 最近记录: |