TimeSpan fixes.
This commit is contained in:
parent
b1a6a4d047
commit
0fa0ac0d1b
1 changed files with 25 additions and 38 deletions
|
@ -23,7 +23,7 @@ class FWIF {
|
||||||
public const TYPE_ARRAY = 0x05; // List of values, terminated with TRAILER
|
public const TYPE_ARRAY = 0x05; // List of values, terminated with TRAILER
|
||||||
public const TYPE_OBJECT = 0x06; // List of values with ASCII names, terminated with TRAILER
|
public const TYPE_OBJECT = 0x06; // List of values with ASCII names, terminated with TRAILER
|
||||||
public const TYPE_DATETIME = 0x07; // A gregorian year, month and day as well as an hour, minute, seconds and millisecond component, variable ranging from 4 to 7 bytes
|
public const TYPE_DATETIME = 0x07; // A gregorian year, month and day as well as an hour, minute, seconds and millisecond component, variable ranging from 4 to 7 bytes
|
||||||
public const TYPE_TIMESPAN = 0x08; // A period of time, follows the same format DATETIME but uses an additional flag to indicate negative periods
|
public const TYPE_TIMESPAN = 0x08; // A period of time, containing days, hours, minutes, seconds and milliseconds, variable ranging from 4 to 6 bytes
|
||||||
|
|
||||||
public const TRAILER = 0xFF; // Termination byte
|
public const TRAILER = 0xFF; // Termination byte
|
||||||
|
|
||||||
|
@ -409,8 +409,7 @@ class FWIF {
|
||||||
return new DateTimeImmutable($dt . 'UTC');
|
return new DateTimeImmutable($dt . 'UTC');
|
||||||
}
|
}
|
||||||
|
|
||||||
private const TIMESPAN_FLAG_YEAR = 0x10000000;
|
private const TIMESPAN_FLAG_DAYS = 0x20000000;
|
||||||
private const TIMESPAN_FLAG_DMY = 0x20000000;
|
|
||||||
private const TIMESPAN_FLAG_NEGA = 0x40000000;
|
private const TIMESPAN_FLAG_NEGA = 0x40000000;
|
||||||
|
|
||||||
private const TIMESPAN_MILLI_SHIFT = 16; // <<
|
private const TIMESPAN_MILLI_SHIFT = 16; // <<
|
||||||
|
@ -419,19 +418,16 @@ class FWIF {
|
||||||
private const TIMESPAN_SECS_SHIFT = 11; // <<
|
private const TIMESPAN_SECS_SHIFT = 11; // <<
|
||||||
private const TIMESPAN_MINS_SHIFT = 5; // <<
|
private const TIMESPAN_MINS_SHIFT = 5; // <<
|
||||||
|
|
||||||
private const TIMESPAN_DAYS_SHIFT = 10; // <<
|
private const TIMESPAN_DAYS_MASK = 0x7FFF;
|
||||||
private const TIMESPAN_MONTH_SHIFT = 6; // <<
|
|
||||||
|
|
||||||
private const TIMESPAN_YEAR_HI_MASK = 0x3F00;
|
private const TIMESPAN_YEAR_DAYS = 365.0;
|
||||||
private const TIMESPAN_YEAR_HI_SHIFT = 8; // >>
|
private const TIMESPAN_MONTH_DAYS = 31.0;
|
||||||
private const TIMESPAN_YEAR_LO_MASK = 0x00FF;
|
|
||||||
|
|
||||||
/* +--------+--------+ w - unsigned 10-bit millisecs y - Y enable flag
|
/* +--------+--------+ w - unsigned 10-bit millisecs n - Negative flag
|
||||||
* |.ndy.www|wwwwwwwS| S - unsigned 6-bit seconds D - unsigned 5-bit day
|
* |.nd..www|wwwwwwwS| S - unsigned 6-bit seconds d - DMY enable flag
|
||||||
* |SSSSSmmm|mmmHHHHH| m - unsigned 6-bit minutes M - unsigned 4-bit month
|
* |SSSSSmmm|mmmHHHHH| m - unsigned 6-bit minutes D - unsigned 15-bit day
|
||||||
* |.DDDDDMM|MMYYYYYY| H - unsigned 5-bit hours Y - unsigned 14-bit year
|
* |.DDDDDDD|DDDDDDDD| H - unsigned 5-bit hours
|
||||||
* |YYYYYYYY| | n - Negative flag
|
* +--------+--------+
|
||||||
* +--------+--------+ d - DMY enable flag
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static function encodeTimeSpan(DateInterval $di, int $flags): string {
|
private static function encodeTimeSpan(DateInterval $di, int $flags): string {
|
||||||
|
@ -441,24 +437,18 @@ class FWIF {
|
||||||
$wsmh |= ( $di->i & self::DATETIME_MINS_MASK) << self::TIMESPAN_MINS_SHIFT;
|
$wsmh |= ( $di->i & self::DATETIME_MINS_MASK) << self::TIMESPAN_MINS_SHIFT;
|
||||||
$wsmh |= ( $di->h & self::DATETIME_HOUR_MASK);
|
$wsmh |= ( $di->h & self::DATETIME_HOUR_MASK);
|
||||||
|
|
||||||
if($di->d > 0 || $di->m > 0 || $di->y > 0) {
|
$days = $di->days;
|
||||||
$wsmh |= self::TIMESPAN_FLAG_DMY;
|
if($days === false) // Best I can come up with on short notice, fuck it
|
||||||
$dmy = ($di->d & self::DATETIME_DAY_MASK) << self::TIMESPAN_DAYS_SHIFT;
|
$days = (int)($di->d + ($di->m * self::TIMESPAN_YEAR_DAYS) + ($di->y * self::TIMESPAN_MONTH_DAYS));
|
||||||
$dmy |= ($di->m & self::DATETIME_MONTH_MASK) << self::TIMESPAN_MONTH_SHIFT;
|
|
||||||
|
|
||||||
if($di->y > 0) {
|
if($days > 0) {
|
||||||
$wsmh |= self::TIMESPAN_FLAG_YEAR;
|
$wsmh |= self::TIMESPAN_FLAG_DAYS;
|
||||||
$dmy |= ($di->y & self::TIMESPAN_YEAR_HI_MASK) >> self::TIMESPAN_YEAR_HI_SHIFT;
|
$days &= self::TIMESPAN_DAYS_MASK;
|
||||||
$y = ($di->y & self::TIMESPAN_YEAR_LO_MASK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$packed = pack('N', $wsmh);
|
$packed = pack('N', $wsmh);
|
||||||
if($wsmh & self::TIMESPAN_FLAG_DMY) {
|
if($wsmh & self::TIMESPAN_FLAG_DAYS)
|
||||||
$packed .= pack('n', $dmy);
|
$packed .= pack('n', $days);
|
||||||
if($wsmh & self::TIMESPAN_FLAG_YEAR)
|
|
||||||
$packed .= chr($y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $packed;
|
return $packed;
|
||||||
}
|
}
|
||||||
|
@ -472,16 +462,13 @@ class FWIF {
|
||||||
$di->i = ($wsmh >> self::TIMESPAN_MINS_SHIFT) & self::DATETIME_MINS_MASK;
|
$di->i = ($wsmh >> self::TIMESPAN_MINS_SHIFT) & self::DATETIME_MINS_MASK;
|
||||||
$di->h = $wsmh & self::DATETIME_HOUR_MASK;
|
$di->h = $wsmh & self::DATETIME_HOUR_MASK;
|
||||||
|
|
||||||
if($wsmh & self::TIMESPAN_FLAG_DMY) {
|
if($wsmh & self::TIMESPAN_FLAG_DAYS) {
|
||||||
$dmy = unpack('n', fread($data, 2))[1];
|
$days = unpack('n', fread($data, 2))[1] & self::TIMESPAN_DAYS_MASK;
|
||||||
$di->d = ($dmy >> self::TIMESPAN_DAYS_SHIFT) & self::DATETIME_DAY_MASK;
|
$di->days = $days;
|
||||||
|
$di->y = (int)floor($days / self::TIMESPAN_YEAR_DAYS);
|
||||||
// OOPS! THESE WILL BE HORRIBLY INACCURATE!
|
$days -= $di->y * self::TIMESPAN_YEAR_DAYS;
|
||||||
// Perhaps go back to the drawing board and tack months and years onto days?
|
$di->m = (int)ceil($days / self::TIMESPAN_MONTH_DAYS);
|
||||||
$di->m = ($dmy >> self::TIMESPAN_MONTH_SHIFT) & self::DATETIME_MONTH_MASK;
|
$di->d = max(0, $days - ($di->m * self::TIMESPAN_MONTH_DAYS));
|
||||||
if($wsmh & self::TIMESPAN_FLAG_YEAR)
|
|
||||||
$di->y = ord(fgetc($data))
|
|
||||||
| (($dmy << self::TIMESPAN_YEAR_HI_SHIFT) & self::TIMESPAN_YEAR_HI_MASK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $di;
|
return $di;
|
||||||
|
|
Reference in a new issue