假设您没有任何更高的单位要解析,并且这些单位始终按大端顺序排列,您可以使用单个正则表达式模式来解析字符串中的所有数据,然后使用简单的算术来计算秒数。
正则表达式将尝试捕获每个可选单元的数量。即使给定的单元不存在,matches 数组仍将保持位置,以便元素始终一致地放置。子模式相当重复,因此如果需要,这将使扩展/减少更容易。
代码:(Demo)
preg_match('/^(?:(d+)d ?)?(?:(d+)h ?)?(?:(d+)m ?)?(?:(d+)s)?$/', $input, $m);
echo ((int) ($m[1] ?? 0) * 86400)
+ ((int) ($m[2] ?? 0) * 3600)
+ ((int) ($m[3] ?? 0) * 60)
+ (int) ($m[4] ?? 0) . " seconds";
如果您的输入数据具有一致的格式并且始终包含每个单位,那么该过程会简单得多,因为sscanf() 可以将数字直接解析为整数。 (Demo)
sscanf($input, '%dd %dh %dm %ds', $d, $h, $m, $s);
echo $d * 86400 + $h * 3600 + $m * 60 + $s;
如果不能保证单元存在或可能以任何顺序存在,您可以使用此函数式样式的 sn-p 来解析表达式。它隔离每个数字单元对,利用查找数组将数字乘以适当的因子,然后对计算求和。 (Demo)
define('UNIT_TO_SECONDS', ['d' => 86400, 'h' => 3600, 'm' => 60, 's' => 1]);
echo array_reduce(
preg_match_all('/(d+)([dhms])/', $input, $m, PREG_SET_ORDER) ? $m : [],
fn($sum, $parts) => $sum + UNIT_TO_SECONDS[$parts[2]] * (int) $parts[1],
0 // initialize $sum with 0 value
);