Skip to content

Commit

Permalink
Share relative date parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
timkelty committed May 25, 2024
1 parent 11dfd5d commit 143da6f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 81 deletions.
51 changes: 51 additions & 0 deletions src/helpers/DateTimeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@ class DateTimeHelper
*/
public const SECONDS_YEAR = 31556874;

public const DURATION_UNITS = [
'sec',
'secs',
'second',
'seconds',
'min',
'mins',
'minute',
'minutes',
'hour',
'hours',
'day',
'days',
'fortnight',
'fortnights',
'forthnight',
'forthnights',
'month',
'months',
'year',
'years',
'week',
'weeks',
];

/**
* @var DateTime[]
* @see pause()
Expand Down Expand Up @@ -809,6 +834,32 @@ public static function humanDurationFromInterval(DateInterval $dateInterval, boo
return static::humanDuration($dateInterval, $showSeconds);
}

/**
* Converts a human-friendly duration (number and unit) to seconds.
*
* @param int $number
* @param string $unit
* @return int
* @since 4.10.0
*/
public static function humanDurationToSeconds(int $number, string $unit): int
{
// So silly that PHP doesn't support "+1 week" http://www.php.net/manual/en/datetime.formats.relative.php
if ($unit === 'week') {
if ($number == 1) {
$number = 7;
$unit = 'days';
} else {
$unit = 'weeks';
}
}

$now = new DateTimeImmutable();
$then = $now->modify("+$number $unit");

return $then->getTimestamp() - $now->getTimestamp();
}

/**
* Normalizes and returns a date string along with the format it was set in.
*
Expand Down
15 changes: 3 additions & 12 deletions src/web/twig/nodes/CacheNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace craft\web\twig\nodes;

use Craft;
use craft\helpers\DateTimeHelper;
use craft\helpers\StringHelper;
use Twig\Compiler;
use Twig\Node\Node;
Expand Down Expand Up @@ -95,18 +96,8 @@ public function compile(Compiler $compiler): void
->write("\$cacheService->endTemplateCache(\$cacheKey$n, $global, ");

if ($durationNum) {
// So silly that PHP doesn't support "+1 week" http://www.php.net/manual/en/datetime.formats.relative.php

if ($durationUnit === 'week') {
if ($durationNum == 1) {
$durationNum = 7;
$durationUnit = 'days';
} else {
$durationUnit = 'weeks';
}
}

$compiler->raw("'+$durationNum $durationUnit'");
$durationSeconds = DateTimeHelper::humanDurationToSeconds($durationNum, $durationUnit);
$compiler->raw("'+$durationSeconds seconds'");
} else {
$compiler->raw('null');
}
Expand Down
21 changes: 2 additions & 19 deletions src/web/twig/nodes/ExpiresNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace craft\web\twig\nodes;

use DateTimeImmutable;
use craft\helpers\DateTimeHelper;
use Twig\Compiler;
use Twig\Node\Node;

Expand All @@ -26,7 +26,7 @@ public function compile(Compiler $compiler): void
{
$durationNum = $this->getAttribute('durationNum');

$duration = $durationNum === null ? null : self::durationInSeconds(
$duration = $durationNum === null ? null : DateTimeHelper::humanDurationToSeconds(
$durationNum,
$this->getAttribute('durationUnit'),
);
Expand All @@ -37,21 +37,4 @@ public function compile(Compiler $compiler): void

$compiler->write("$line\n");
}

private static function durationInSeconds($number, $unit): int
{
if ($unit === 'week') {
if ($number == 1) {
$number = 7;
$unit = 'days';
} else {
$unit = 'weeks';
}
}

$now = new DateTimeImmutable();
$then = $now->modify("+$number $unit");

return $then->getTimestamp() - $now->getTimestamp();
}
}
27 changes: 2 additions & 25 deletions src/web/twig/tokenparsers/CacheTokenParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace craft\web\twig\tokenparsers;

use craft\helpers\DateTimeHelper;
use craft\web\twig\nodes\CacheNode;
use Twig\Token;
use Twig\TokenParser\AbstractTokenParser;
Expand Down Expand Up @@ -58,31 +59,7 @@ public function parse(Token $token): CacheNode
if ($stream->test(Token::NAME_TYPE, 'for')) {
$stream->next();
$attributes['durationNum'] = $stream->expect(Token::NUMBER_TYPE)->getValue();
$attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE,
[
'sec',
'secs',
'second',
'seconds',
'min',
'mins',
'minute',
'minutes',
'hour',
'hours',
'day',
'days',
'fortnight',
'fortnights',
'forthnight',
'forthnights',
'month',
'months',
'year',
'years',
'week',
'weeks',
])->getValue();
$attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE, DateTimeHelper::DURATION_UNITS)->getValue();
} elseif ($stream->test(Token::NAME_TYPE, 'until')) {
$stream->next();
$nodes['expiration'] = $parser->getExpressionParser()->parseExpression();
Expand Down
27 changes: 2 additions & 25 deletions src/web/twig/tokenparsers/ExpiresTokenParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace craft\web\twig\tokenparsers;

use craft\helpers\DateTimeHelper;
use craft\web\twig\nodes\ExpiresNode;
use Twig\Token;
use Twig\TokenParser\AbstractTokenParser;
Expand Down Expand Up @@ -41,31 +42,7 @@ public function parse(Token $token): ExpiresNode
} elseif ($stream->test(Token::NAME_TYPE, 'for')) {
$stream->next();
$attributes['durationNum'] = $stream->expect(Token::NUMBER_TYPE)->getValue();
$attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE,
[
'sec',
'secs',
'second',
'seconds',
'min',
'mins',
'minute',
'minutes',
'hour',
'hours',
'day',
'days',
'fortnight',
'fortnights',
'forthnight',
'forthnights',
'month',
'months',
'year',
'years',
'week',
'weeks',
])->getValue();
$attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE, DateTimeHelper::DURATION_UNITS)->getValue();
}

$stream->expect(Token::BLOCK_END_TYPE);
Expand Down

0 comments on commit 143da6f

Please sign in to comment.