PHP解析时间与控制台?
当输入的格式不同(如下面的输出示例所示)时,如何以秒为单位计算时间输入 使用此格式,所有零件都是可选的:PHP解析时间与控制台?,php,Php,当输入的格式不同(如下面的输出示例所示)时,如何以秒为单位计算时间输入 使用此格式,所有零件都是可选的: 5d 4h 3m 2s -> 5 days, 4 hours, 3 minutes and 2 seconds 4h 2s -> 4 hours and 2 seconds 3m -> 3 minutes 05: 04: 03: 02 -> 5 days, 4 hours, 3 minutes and 2 seconds 4:03:02 -> 4 hours,
5d 4h 3m 2s -> 5 days, 4 hours, 3 minutes and 2 seconds
4h 2s -> 4 hours and 2 seconds
3m -> 3 minutes
05: 04: 03: 02 -> 5 days, 4 hours, 3 minutes and 2 seconds
4:03:02 -> 4 hours, 3 minutes and 2 seconds
05: 00: 03: 02 -> 5 days, 3 minutes and 2 seconds
02 -> 2 seconds
使用此格式,零件有时是可选的:
5d 4h 3m 2s -> 5 days, 4 hours, 3 minutes and 2 seconds
4h 2s -> 4 hours and 2 seconds
3m -> 3 minutes
05: 04: 03: 02 -> 5 days, 4 hours, 3 minutes and 2 seconds
4:03:02 -> 4 hours, 3 minutes and 2 seconds
05: 00: 03: 02 -> 5 days, 3 minutes and 2 seconds
02 -> 2 seconds
我希望得到以下输出:
> php time.php 1d 6h 20m 2s
> 109.202 seconds
> php time.php 3:50
> 230 seconds
> php time.php 4: 23: 45: 02
> 431.102 seconds
> php time.php 23m
> 1.380 seconds
到目前为止,我已经能够将输入秒转换为时间格式,但在5个小时的努力后,我放弃了上述问题:
您可以使用
preg\u match\u all
将输入拆分为成对的数字和后缀,然后迭代这些数字和后缀以计算秒数:
function seconds($input) {
preg_match_all("/(\d+)(\S)/", "$input:", $matches, PREG_SET_ORDER);
$letters = "smhd";
$durations = ["s" => 1, "m" => 60, "h" => 60*60, "d" => 60*60*24];
$seconds = 0;
foreach (array_reverse($matches) as list($all, $num, $code)) {
$i = strpos($letters, $code);
if ($i === false) $code = $letters[$i = 0];
$letters = substr($letters, $i+1);
$seconds += $durations[$code] * $num;
}
return $seconds;
}
function test($input) {
$seconds = number_format(seconds($input));
echo "$input => $seconds seconds\n";
}
test("1d 6h 20m 2s"); // 109.202 seconds
test("3:50"); // 230 seconds
test("4: 23: 45: 02"); // 431.102 seconds
test("23m"); // 1.380 seconds
以下内容可能有些过分,但也可能说明如果您希望代码可扩展且易于重用,如何解决此问题:
<?php
declare(strict_types=1);
error_reporting(-1);
ini_set('display_errors', 'On');
interface TimeStringParser
{
public function accepts(string $input): bool;
public function parse(string $input): int;
}
final class InputWithUnits implements TimeStringParser
{
public function accepts(string $input): bool
{
foreach (preg_split('/\s+/', $input) as $chunk) {
if (! preg_match('/^\d+(d|h|m|s)$/', $chunk)) {
return false;
}
}
return true;
}
public function parse(string $input): int
{
if (! $this->accepts($input)) {
throw new \InvalidArgumentException('Invalid input.');
}
$result = 0;
if (preg_match_all('/((?<value>\d+)(?<unit>d|h|m|s))/', $input, $matches)) {
foreach ($matches['unit'] as $i => $unit) {
$value = (int) $matches['value'][$i];
switch ($unit) {
case 'd': $result += $value * 86400; break;
case 'h': $result += $value * 3600; break;
case 'm': $result += $value * 60; break;
case 's': $result += $value * 1; break;
}
}
}
return $result;
}
}
final class InputWithoutUnits implements TimeStringParser
{
public function accepts(string $input): bool
{
foreach (explode(':', $input) as $chunk) {
if (! preg_match('/^\d+$/', trim($chunk))) {
return false;
}
}
return true;
}
public function parse(string $input): int
{
if (! $this->accepts($input)) {
throw new \InvalidArgumentException('Invalid input.');
}
$multiplier = [1, 60, 3600, 86400];
$result = 0;
foreach (array_reverse(explode(':', $input)) as $chunk) {
$value = (int) trim($chunk);
$result += $value * array_shift($multiplier);
}
return $result;
}
}
final class ParserComposite implements TimeStringParser
{
private $parsers;
public function __construct(TimeStringParser ...$parsers)
{
$this->parsers = $parsers;
}
public function accepts(string $input): bool
{
foreach ($this->parsers as $parser) {
if ($parser->accepts($input)) {
return true;
}
}
return false;
}
public function parse(string $input): int
{
foreach ($this->parsers as $parser) {
if ($parser->accepts($input)) {
return $parser->parse($input);
}
}
throw new \InvalidArgumentException('Invalid input.');
}
}
$parser = new ParserComposite(
new InputWithUnits(),
new InputWithoutUnits()
);
$testCases = [
'5d 4h 3m 2s',
'4h 2s',
'3m',
'05: 04: 03: 02',
'4:03:02',
'05: 00: 03: 02',
'02',
'23m',
'2e-5'
];
foreach ($testCases as $testCase) {
if ($parser->accepts($testCase)) {
printf("%-'.20s: %8d\n", $testCase, $parser->parse($testCase));
}
else {
printf("%-'.20s: unsupported\n", $testCase);
}
}
你开始编码了吗,还是你希望这里的人能帮你完成这一切?真不知道为什么有人认为这个问题值得投票表决?@RiggsFolly这个问题本身与现在大多数其他问题相比是一个有趣的问题。它只是没有显示出任何努力。我添加了一些代码。好的,你要做的第一件事是测试输入,看看使用了哪种格式,这样你就知道如何正确解读它的内容。谢谢你的这段代码。非常感谢您的努力,而且效果也很好。