Skip to content

Commit

Permalink
feat(datetime): Introduce DateTime component
Browse files Browse the repository at this point in the history
Signed-off-by: azjezz <azjezz@protonmail.com>
  • Loading branch information
azjezz committed Mar 21, 2024
1 parent 5f0aeac commit 6bf3a47
Show file tree
Hide file tree
Showing 57 changed files with 4,609 additions and 69 deletions.
1 change: 1 addition & 0 deletions config/.phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

<rule ref="PSR2">
<type>error</type>
<exclude name="PSR2.ControlStructures.ControlStructureSpacing.SpacingAfterOpenBrace"/>
</rule>

<rule ref="PSR12">
Expand Down
17 changes: 11 additions & 6 deletions examples/async/usleep.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,27 @@
namespace Psl\Example\IO;

use Psl\Async;
use Psl\DateTime;
use Psl\IO;

require __DIR__ . '/../../vendor/autoload.php';

Async\main(static function (): int {
$start = time();
$start = microtime(true);

Async\concurrently([
static fn() => Async\sleep(2.0),
static fn() => Async\sleep(2.0),
static fn() => Async\sleep(2.0),
static fn() => Async\sleep(DateTime\Duration::hours(0)),
static fn() => Async\sleep(DateTime\Duration::minutes(0)),
static fn() => Async\sleep(DateTime\Duration::zero()),
static fn() => Async\sleep(DateTime\Duration::seconds(2)),
static fn() => Async\sleep(DateTime\Duration::nanoseconds(20000000)),
static fn() => Async\sleep(DateTime\Duration::microseconds(200000)),
static fn() => Async\sleep(DateTime\Duration::milliseconds(2000)),
]);

$duration = time() - $start;
$duration = DateTime\Duration::microseconds((int) ((microtime(true) - $start) * DateTime\MICROSECONDS_PER_SECOND));

IO\write_error_line("duration: %d.", $duration);
IO\write_error_line("duration: %s.", $duration->toString(max_decimals: 5));

return 0;
});
55 changes: 55 additions & 0 deletions sample.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

use Psl\DateTime;
use Psl\IO;
use Psl\Async;
use Psl\Locale;

use DateTime as NativeDateTime;
use DateTimeZone as NativeDateTimeZone;

require 'vendor/autoload.php';

Async\main(static function(): void {
$someday = DateTime\DateTime::fromTimestamp(
DateTime\Timestamp::fromRaw(1711846900),
DateTime\Timezone::EuropeLondon,
);

IO\write_line('The offset of the timezone: %s', $someday->getTimezone()->getOffset($someday)->getTotalMinutes());
IO\write_line('The location of the timezone: %s', json_encode($someday->getTimezone()->getLocation()));

$today = DateTime\DateTime::now(DateTime\Timezone::EuropeLondon);
$today_native = new NativeDateTime('now', new NativeDateTimeZone('Europe/London'));

$that_day = $today->plusDays(24);
$that_day_native = $today_native->modify('+24 days');

var_dump($that_day->format(DateTime\DateFormat::Iso8601), $that_day_native->format(DateTimeInterface::ATOM));
var_dump($that_day->getTimezone()->name, $that_day_native->getTimezone()->getName());
var_dump($that_day->getTimezone()->getOffset($that_day), $that_day_native->getTimezone()->getOffset($that_day_native));

$now = DateTime\DateTime::now(DateTime\Timezone::EuropeLondon);

foreach (DateTime\DateFormat::cases() as $case) {
IO\write_line('time: %s -> %s', $case->name, $now->format(format: $case, locale: Locale\Locale::English));
}

IO\write_line('The offset of the timezone: %s', $now->getTimezone()->getOffset($now)->toString());

$after_4_months = $now->withMonth(4);
IO\write_line('The offset of the timezone: %s', $after_4_months->getTimezone()->getOffset($after_4_months)->toString());

$future = $now->withYear(2051)->withMonth(4)->withDay(2)->withHours(14)->withMinutes(51)->withSeconds(21)->withNanoseconds(124636);

$now_timestamp = $now->getTimestamp();
$future_timestamp = $future->getTimestamp();

var_dump($now_timestamp->compare($future_timestamp), $future->isAfter($now), $now->isBeforeOrAtTheSameTime($future));

IO\write_line('The offset of the future timezone: %s', $future->getTimezone()->getOffset($future)->toString());
IO\write_line('Time: %s', $now->getTimestamp()->format($now->getTimezone(), locale: Locale\Locale::French));

$now = DateTime\DateTime::now(DateTime\Timezone::EuropeLondon);
IO\write_line('Time: %s', json_encode($now));
});
17 changes: 13 additions & 4 deletions src/Psl/Async/Scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Closure;
use Psl;
use Psl\DateTime;
use Revolt\EventLoop;
use Revolt\EventLoop\Driver;
use Revolt\EventLoop\InvalidCallbackError;
Expand Down Expand Up @@ -114,35 +115,43 @@ public static function defer(Closure $callback): string
/**
* Delay the execution of a callback.
*
* @param float $delay The amount of time, to delay the execution for in seconds.
* @param DateTime\Duration|float $delay The amount of time, to delay the execution for in seconds.
* @param Closure(string): void $callback The callback to delay.
*
* @return non-empty-string A unique identifier that can be used to cancel, enable or disable the callback.
*
* @see EventLoop::delay()
*/
public static function delay(float $delay, Closure $callback): string
public static function delay(DateTime\Duration|float $delay, Closure $callback): string
{
if ($delay instanceof DateTime\Duration) {
$delay = $delay->getTotalSeconds();
}

/** @var non-empty-string */
return EventLoop::delay($delay, $callback);
}

/**
* Repeatedly execute a callback.
*
* @param float $interval The time interval, to wait between executions in seconds.
* @param DateTime\Duration|float $interval The time interval, to wait between executions in seconds.
* @param Closure(string): void $callback The callback to repeat.
*
* @return non-empty-string A unique identifier that can be used to cancel, enable or disable the callback.
*
* @see EventLoop::repeat()
*/
public static function repeat(float $interval, Closure $callback): string
public static function repeat(DateTime\Duration|float $interval, Closure $callback): string
{
if ($interval instanceof DateTime\Duration) {
$interval = $interval->getTotalSeconds();
}
/** @var non-empty-string */
return EventLoop::repeat($interval, $callback);
}


/**
* Enable a callback to be active starting in the next tick.
*
Expand Down
7 changes: 6 additions & 1 deletion src/Psl/Async/sleep.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@

namespace Psl\Async;

use Psl\DateTime;
use Revolt\EventLoop;

/**
* Non-blocking sleep for the specified number of seconds.
*/
function sleep(float $seconds): void
function sleep(DateTime\Duration|float $seconds): void
{
if ($seconds instanceof DateTime\Duration) {
$seconds = $seconds->getTotalSeconds();
}

$suspension = EventLoop::getSuspension();
$watcher = EventLoop::delay($seconds, static fn () => $suspension->resume());

Expand Down
24 changes: 24 additions & 0 deletions src/Psl/DateTime/DateFormat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Psl\DateTime;

/**
* An enumeration of common date format strings.
*
* This enum provides a collection of standardized date format strings for various protocols
* and standards, such as RFC 2822, ISO 8601, HTTP headers, and more.
*/
enum DateFormat: string
{
case Rfc2822 = 'EEE, dd MMM yyyy HH:mm:ss Z';
case Iso8601 = 'yyyy-MM-dd\'T\'HH:mm:ssXXX';
case Http = 'EEE, dd MMM yyyy HH:mm:ss zzz';
case Cookie = 'EEEE, dd-MMM-yyyy HH:mm:ss zzz';
case Sql = 'yyyy-MM-dd HH:mm:ss';
case XmlRpc = 'yyyyMMdd\'T\'HH:mm:ss';
case IsoWeekDate = 'Y-ww-E';
case IsoOrdinalDate = 'yyyy-DDD';
case JulianDay = 'yyyy DDD';
}
Loading

0 comments on commit 6bf3a47

Please sign in to comment.