Changes to timew() and wtime() to leverage last 2 bits for 4 year timestamp, making msgid checking valid according to FTSC. Added a test suite for timew()/wtime().
This commit is contained in:
parent
ee15274478
commit
fa2e74eaca
@ -103,17 +103,18 @@ if (! function_exists('timew')) {
|
||||
* are unique using 1/10th second precision.
|
||||
*
|
||||
* Time is:
|
||||
* + 02 bits unused
|
||||
* + 02 bits least significant bits of year - giving us a 4 year timestamp
|
||||
* + 04 bits Month
|
||||
* + 05 bits Day
|
||||
* + 05 bits Hour
|
||||
* + 06 bits Min
|
||||
* + 06 bits Sec
|
||||
* + 04 bits 10th Sec
|
||||
* = 32 (2 bits free)
|
||||
* = 32 bits
|
||||
*
|
||||
* @param Carbon|null $time
|
||||
* @return int
|
||||
* @todo Since this is used as part of our msgid, we need to use the first 2 bits to get our 3 year unique msgid, ie: year&0x03
|
||||
*/
|
||||
function timew(Carbon $time=NULL): int
|
||||
{
|
||||
@ -130,19 +131,30 @@ if (! function_exists('timew')) {
|
||||
|
||||
$delay = $time->getPreciseTimestamp(1);
|
||||
|
||||
$t = ($time->month & 0xf) << 5;
|
||||
$t = 0;
|
||||
$t = ($t | $time->year & 0x3) << 4;
|
||||
$t = ($t | ($time->month & 0xf)) << 5;
|
||||
$t = ($t | ($time->day & 0x1f)) << 5;
|
||||
$t = ($t | ($time->hour & 0x1f)) << 6;
|
||||
$t = ($t | ($time->minute & 0x3f)) << 6;
|
||||
$t = ($t | ($time->second & 0x3f));
|
||||
$t = ($t | ($time->second & 0x3f)) << 4;
|
||||
$t = ($t | ((int)($time->milli/100)) & 0xf);
|
||||
|
||||
return hexdec(sprintf('%07x%1x',$t,(round($time->milli/100) & 0x7f)));
|
||||
return $t;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('wtime')) {
|
||||
/**
|
||||
* Convert a 40 bit integer into a time.
|
||||
* We need to filter out loose bits, ie:
|
||||
* + year all bits valid
|
||||
* + month 11xx and 0000 are invalid
|
||||
* + day all bits valid except 0000
|
||||
* + hour 11xxx are invalid
|
||||
* + min 1111xx are invalid
|
||||
* + sec 1111xx are invalid
|
||||
* + 1/2 11xx, 101x are invalid
|
||||
* @see timew()
|
||||
*
|
||||
* @param int $time
|
||||
@ -158,25 +170,36 @@ if (! function_exists('wtime')) {
|
||||
if ($time > pow(2,26)-1) {
|
||||
$milli = ($time & 0xf);
|
||||
$time = $time >> 4;
|
||||
if ($milli > 9)
|
||||
$milli = 9;
|
||||
|
||||
} else {
|
||||
$milli = 0;
|
||||
}
|
||||
|
||||
$sec = ($time & 0x3f);
|
||||
if ($sec > 59)
|
||||
$sec = 59;
|
||||
$time = $time >> 6;
|
||||
|
||||
$min = ($time & 0x3f);
|
||||
if ($min > 59)
|
||||
$min = 59;
|
||||
$time = $time >> 6;
|
||||
|
||||
$hr = ($time & 0x1f);
|
||||
if ($hr > 23)
|
||||
$hr = 23;
|
||||
$time = $time >> 5;
|
||||
|
||||
$day = ($time & 0x1f);
|
||||
$time = $time >> 5;
|
||||
|
||||
$month = ($time & 0x1f);
|
||||
$month = ($time & 0xf);
|
||||
if ($month > 12)
|
||||
$month = 12;
|
||||
$time = $time >> 4;
|
||||
|
||||
return Carbon::create($year,$month,$day,$hr,$min,$sec+$milli/10);
|
||||
return Carbon::create(($year & 0xffc)+$time,$month,$day,$hr,$min,$sec+$milli/10);
|
||||
}
|
||||
}
|
59
tests/Unit/TimeWTest.php
Normal file
59
tests/Unit/TimeWTest.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TimeWTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* A basic unit test example.
|
||||
*/
|
||||
public function test_timew(): void
|
||||
{
|
||||
$date = Carbon::createFromFormat('Y-m-d H:i:s.v','2023-12-07 12:13:14.567');
|
||||
|
||||
$this->assertEquals(4042011877,timew($date));
|
||||
|
||||
$date = Carbon::createFromFormat('Y-m-d H:i:s.v','2019-12-07 12:13:14.567');
|
||||
|
||||
$this->assertEquals(4042011877,timew($date));
|
||||
|
||||
$date = Carbon::createFromFormat('Y-m-d H:i:s.v','2022-12-07 01:28:50.400');
|
||||
|
||||
$this->assertEquals(2967565092,timew($date));
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic unit test example.
|
||||
*/
|
||||
public function test_wtime(): void
|
||||
{
|
||||
$date = Carbon::createFromFormat('Y-m-d H:i:s.v','2023-12-07 12:13:14.5');
|
||||
|
||||
$this->assertEquals($date,wtime(4042011877,2022));
|
||||
|
||||
$date = Carbon::createFromFormat('Y-m-d H:i:s.v','2019-12-07 12:13:14.5');
|
||||
|
||||
$this->assertEquals($date,wtime(4042011877,2018));
|
||||
|
||||
$date = Carbon::createFromFormat('Y-m-d H:i:s.v','2022-12-07 01:28:50.400');
|
||||
|
||||
$this->assertEquals($date,wtime(2967565092,2022));
|
||||
}
|
||||
|
||||
public function test_random_time(): void
|
||||
{
|
||||
$times = [];
|
||||
$now = Carbon::now()->milli(rand(0,9)*100);
|
||||
|
||||
for ($i=0;$i<1000;$i++) {
|
||||
$ran = $now->clone()->addYears(rand(-50,50))->addDays(rand(-365,365))->addHours(rand(-24,24))->addMinutes(rand(-60,60))->addSeconds(rand(-60,60));
|
||||
$times[timew($ran)] = $ran;
|
||||
}
|
||||
|
||||
foreach ($times as $wtime => $time)
|
||||
$this->assertEquals($time,wtime($wtime,$time->year));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user