Allow parsing of more flexible interval strings including long names (day, hour, minute, second, millisecond), negative values, no spaces between components, and throwing exceptions on invalid input if requested. The following types are now allowed - d|day|days - h|hour|hours - m|min|mins|minute|minutes - s|sec|secs|second|seconds - ms|msec|msecs|msecond|mseconds|millis|millisec|millisecs|millisecond|milliseconds Also fix the milisecond parsing that was done completly wrong the milliseoncds where just added after a "." as decimals without converting them at all. Now the value is divided by 1000 and added to the existing number, and as before only if ms exist The negative check is now included in the main parse regex, so a second regex check is no longer necessary Spaces between values, before or anywhere are now more flexible. Exceptions are thrown if the regex cannot parse anything, or it returns only one master entry and no matches
604 lines
20 KiB
PHP
604 lines
20 KiB
PHP
<?php // phpcs:ignore warning
|
|
|
|
/**
|
|
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
error_reporting(E_ALL | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
|
|
|
ob_start();
|
|
|
|
// basic class test file
|
|
define('USE_DATABASE', false);
|
|
// sample config
|
|
require 'config.php';
|
|
// define log file id
|
|
$LOG_FILE_ID = 'classTest-datetime';
|
|
ob_end_flush();
|
|
|
|
use CoreLibs\Combined\DateTime;
|
|
use CoreLibs\Debug\Support as DgS;
|
|
|
|
$log = new CoreLibs\Logging\Logging([
|
|
'log_folder' => BASE . LOG,
|
|
'log_file_id' => $LOG_FILE_ID,
|
|
'log_per_date' => true,
|
|
]);
|
|
$datetime_class = 'CoreLibs\Combined\DateTime';
|
|
|
|
$PAGE_NAME = 'TEST CLASS: DATE/TIME';
|
|
print "<!DOCTYPE html>";
|
|
print "<html><head><title>" . $PAGE_NAME . "</title></head>";
|
|
print "<body>";
|
|
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
|
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
|
|
|
// class
|
|
$timestamp = 1622788315.123456;
|
|
// static
|
|
print "S::DATESTRINGFORMAT(sm:0): $timestamp: " . $datetime_class::dateStringFormat($timestamp) . "<br>";
|
|
|
|
// time string thest
|
|
$timestamp = 5887998.33445;
|
|
$time_string = DateTime::timeStringFormat($timestamp);
|
|
print "PLANE TIME STRING: " . $timestamp . "<br>";
|
|
print "TIME STRING TEST: " . $time_string . "<br>";
|
|
print "REVERSE TIME STRING: " . DateTime::stringToTime($time_string) . "<br>";
|
|
if (round($timestamp, 4) == DateTime::stringToTime($time_string)) {
|
|
print "REVERSE TIME STRING MATCH<br>";
|
|
} else {
|
|
print "REVERSE TRIME STRING DO NOT MATCH<br>";
|
|
}
|
|
print "<hr>";
|
|
$timestamps = [
|
|
1622788315.123456,
|
|
-1622788315.456789
|
|
];
|
|
foreach ($timestamps as $timestamp) {
|
|
print "DATESTRINGFORMAT(sm:0:0): $timestamp: " . DateTime::dateStringFormat($timestamp) . "<br>";
|
|
print "DATESTRINGFORMAT(sm:1:0): $timestamp: " . DateTime::dateStringFormat($timestamp, true) . "<br>";
|
|
print "DATESTRINGFORMAT(sm:1:1): $timestamp: " . DateTime::dateStringFormat($timestamp, true, true) . "<br>";
|
|
}
|
|
print "<hr>";
|
|
// $interval = 0;
|
|
// $interval = 1000000;
|
|
// $interval = 123456;
|
|
// $interval = 3600;
|
|
$interval = 3601;
|
|
// $interval = 86400;
|
|
// $interval = 86401;
|
|
// $interval = (86400 * 606) + 16434.5;
|
|
// $interval = 1.5;
|
|
// $interval = 123456;
|
|
// $interval = 120.1;
|
|
// $interval = 1641515890;
|
|
// $interval = 0.123456;
|
|
// $interval = 1641515890;
|
|
// $interval = 999999999999999999;
|
|
// $interval = 60;
|
|
try {
|
|
// print "Test-DEP: [$interval] "
|
|
// . intervalStringFormatDeprecated(
|
|
// $interval,
|
|
// truncate_after: '',
|
|
// natural_seperator: false,
|
|
// name_space_seperator: false,
|
|
// show_microseconds: true,
|
|
// short_time_name: true,
|
|
// skip_last_zero: true,
|
|
// skip_zero: false,
|
|
// show_only_days: false,
|
|
// auto_fix_microseconds: false,
|
|
// truncate_nanoseconds: false,
|
|
// truncate_zero_seconds_if_microseconds: true,
|
|
// )
|
|
// // . " => "
|
|
// // . DateTime::intervalStringFormat($interval)
|
|
// . "<br>";
|
|
print "Test-ACT: [$interval] "
|
|
. DateTime::intervalStringFormat(
|
|
$interval,
|
|
truncate_after: '',
|
|
natural_seperator: false,
|
|
name_space_seperator: false,
|
|
show_microseconds: true,
|
|
short_time_name: true,
|
|
skip_last_zero: true,
|
|
skip_zero: false,
|
|
show_only_days: false,
|
|
auto_fix_microseconds: false,
|
|
truncate_nanoseconds: false,
|
|
truncate_zero_seconds_if_microseconds: true,
|
|
)
|
|
. " => "
|
|
. DateTime::intervalStringFormat($interval)
|
|
. "<br>";
|
|
print "DEFAULT-DEP: " . intervalStringFormatDeprecated($interval) . "<br>";
|
|
print "DEFAULT-ACT: " . DateTime::intervalStringFormat($interval) . "<br>";
|
|
$show_micro = true;
|
|
// print "COMPATIBLE Test-DEP: " .
|
|
// intervalStringFormatDeprecated(
|
|
// $interval,
|
|
// show_microseconds: $show_micro,
|
|
// show_only_days: true,
|
|
// skip_zero: false,
|
|
// skip_last_zero: false,
|
|
// truncate_nanoseconds: true,
|
|
// truncate_zero_seconds_if_microseconds: false
|
|
// ) . "<br>";
|
|
print "COMPATIBLE Test-ACT: " .
|
|
DateTime::intervalStringFormat(
|
|
$interval,
|
|
show_microseconds: $show_micro,
|
|
show_only_days: true,
|
|
skip_zero: false,
|
|
skip_last_zero: false,
|
|
truncate_nanoseconds: true,
|
|
truncate_zero_seconds_if_microseconds: false
|
|
) . "<br>";
|
|
print "ORIGINAL: " . DateTime::timeStringFormat($interval, $show_micro) . "<br>";
|
|
} catch (\UnexpectedValueException $e) {
|
|
print "ERROR: " . $e->getMessage() . "<br><pre>" . $e . "</pre><br>";
|
|
} catch (\LengthException $e) {
|
|
print "ERROR interval: " . $e->getMessage() . "<br><pre>" . $e . "</pre><br>";
|
|
}
|
|
print "<hr>";
|
|
$intervals = [
|
|
['i' => 0, 'sm' => true],
|
|
['i' => 0.0, 'sm' => true],
|
|
['i' => 1.5, 'sm' => true],
|
|
['i' => 1.05, 'sm' => true],
|
|
['i' => 1.005, 'sm' => true],
|
|
['i' => 1.0005, 'sm' => true],
|
|
];
|
|
foreach ($intervals as $int) {
|
|
$info = 'ts:' . $int['i'] . '|' . 'sm:' . $int['sm'];
|
|
print "[tsf] ZERO TIME STRING [$info]: "
|
|
. DateTime::timeStringFormat($int['i'], $int['sm']) . "<br>";
|
|
print "[isf] ZERO TIME STRING [$info]: "
|
|
. DateTime::intervalStringFormat($int['i'], show_microseconds:$int['sm']) . "<br>";
|
|
}
|
|
print "<hr>";
|
|
$intervals = [
|
|
[
|
|
'i' => 788315.123456,
|
|
'truncate_after' => '',
|
|
'natural_seperator' => false,
|
|
'name_space_seperator' => false,
|
|
'show_microseconds' => true,
|
|
'short_time_name' => true,
|
|
'skip_last_zero' => false,
|
|
'skip_zero' => true,
|
|
'show_only_days' => false,
|
|
'auto_fix_microseconds' => false,
|
|
'truncate_nanoseconds' => false
|
|
],
|
|
[
|
|
'i' => 788315.123456,
|
|
'truncate_after' => '',
|
|
'natural_seperator' => true,
|
|
'name_space_seperator' => true,
|
|
'show_microseconds' => true,
|
|
'short_time_name' => true,
|
|
'skip_last_zero' => false,
|
|
'skip_zero' => true,
|
|
'show_only_days' => false,
|
|
'auto_fix_microseconds' => false,
|
|
'truncate_nanoseconds' => false
|
|
],
|
|
];
|
|
foreach ($intervals as $int) {
|
|
$info = $int['i'];
|
|
try {
|
|
print "INTRVALSTRINGFORMAT(sm:0): $info: "
|
|
. DateTime::intervalStringFormat(
|
|
$int['i'],
|
|
truncate_after: (string)$int['truncate_after'],
|
|
natural_seperator: $int['natural_seperator'],
|
|
name_space_seperator: $int['name_space_seperator'],
|
|
show_microseconds: $int['show_microseconds'],
|
|
short_time_name: $int['short_time_name'],
|
|
skip_last_zero: $int['skip_last_zero'],
|
|
skip_zero: $int['skip_zero'],
|
|
show_only_days: $int['show_only_days'],
|
|
auto_fix_microseconds: $int['auto_fix_microseconds'],
|
|
truncate_nanoseconds: $int['truncate_nanoseconds'],
|
|
) . "<br>";
|
|
} catch (\UnexpectedValueException $e) {
|
|
print "ERROR: " . $e->getMessage() . "<br><pre>" . $e . "</pre><br>";
|
|
} catch (\LengthException $e) {
|
|
print "ERROR interval: " . $e->getMessage() . "<br><pre>" . $e . "</pre><br>";
|
|
}
|
|
}
|
|
print "<hr>";
|
|
// convert and reverste tests
|
|
$intervals = [
|
|
788315.123456,
|
|
-123.456
|
|
];
|
|
foreach ($intervals as $interval) {
|
|
print "TIMESTRINGFORMAT(sm:0): $interval: " . DateTime::timeStringFormat($interval, false) . "<br>";
|
|
$reverse_interval = DateTime::timeStringFormat($interval);
|
|
print "TIMESTRINGFORMAT(sm:1): $interval: " . $reverse_interval . "<br>";
|
|
print "STRINGTOTIME: $reverse_interval: " . DateTime::stringToTime($reverse_interval) . "<br>";
|
|
}
|
|
print "<hr>";
|
|
$interval_strings = [
|
|
'10d 5h 30m 15s 123456ms',
|
|
'18999d 0h 38m 10s 1235ms',
|
|
'18999 d 0 h 38 m 10s 1235ms',
|
|
'-2h 15m 5s',
|
|
'45s 500ms',
|
|
'0s',
|
|
'0ms',
|
|
'1s 5ms',
|
|
'1s 50ms',
|
|
'1s 500ms',
|
|
'1s 5000ms',
|
|
'10day 5hour 30min 15sec 123456millis',
|
|
'10day 5hour 30min 15sec 123456millisec',
|
|
'10day 5hour 30min 15sec 123456msec',
|
|
'-2days 3hours 15minutes 30seconds 250milliseconds',
|
|
'',
|
|
' ',
|
|
'invalid',
|
|
];
|
|
foreach ($interval_strings as $interval_string) {
|
|
print "STRINGTOTIME: $interval_string: " . DateTime::stringToTime($interval_string) . "<br>";
|
|
try {
|
|
// test exception
|
|
DateTime::stringToTime($interval_string, throw_exception:true);
|
|
} catch (\InvalidArgumentException $e) {
|
|
print "ERROR: " . $e->getMessage() . "<br><pre>" . $e . "</pre><br>";
|
|
}
|
|
}
|
|
print "<hr>";
|
|
$check_dates = [
|
|
'2021-05-01',
|
|
'2021-05-40'
|
|
];
|
|
foreach ($check_dates as $check_date) {
|
|
print "CHECKDATE: $check_date: " . (string)DateTime::checkDate($check_date) . "<br>";
|
|
}
|
|
print "<hr>";
|
|
$check_datetimes = [
|
|
'2021-05-01',
|
|
'2021-05-40',
|
|
'2021-05-01 12:13:14',
|
|
'2021-05-40 12:13:14',
|
|
'2021-05-01 25:13:14',
|
|
];
|
|
foreach ($check_datetimes as $check_datetime) {
|
|
print "CHECKDATETIME: $check_datetime: " . (string)DateTime::checkDateTime($check_datetime) . "<br>";
|
|
}
|
|
print "<hr>";
|
|
$compare_dates = [
|
|
[ '2021-05-01', '2021-05-02', ],
|
|
[ '2021-05-02', '2021-05-01', ],
|
|
[ '2021-05-02', '2021-05-02', ],
|
|
[ '2017/1/5', '2017-01-05', ],
|
|
];
|
|
// compareDate
|
|
foreach ($compare_dates as $compare_date) {
|
|
print "COMPAREDATE: $compare_date[0] = $compare_date[1]: "
|
|
. (string)DateTime::compareDate($compare_date[0], $compare_date[1]) . "<br>";
|
|
}
|
|
print "<hr>";
|
|
$compare_datetimes = [
|
|
[ '2021-05-01', '2021-05-02', ],
|
|
[ '2021-05-02', '2021-05-01', ],
|
|
[ '2021-05-02', '2021-05-02', ],
|
|
[ '2021-05-01 10:00:00', '2021-05-01 11:00:00', ],
|
|
[ '2021-05-01 11:00:00', '2021-05-01 10:00:00', ],
|
|
[ '2021-05-01 10:00:00', '2021-05-01 10:00:00', ],
|
|
];
|
|
foreach ($compare_datetimes as $compare_datetime) {
|
|
print "COMPAREDATE: $compare_datetime[0] = $compare_datetime[1]: "
|
|
. (string)DateTime::compareDateTime($compare_datetime[0], $compare_datetime[1]) . "<br>";
|
|
}
|
|
|
|
print "<hr>";
|
|
print "<h2>calcDaysInterval</h2>";
|
|
$compare_dates = [
|
|
[ '2021-05-01', '2021-05-10', ],
|
|
[ '2021-05-10', '2021-05-01', ],
|
|
[ '2021-05-02', '2021-05-01', ],
|
|
[ '2021-05-02', '2021-05-02', ],
|
|
];
|
|
foreach ($compare_dates as $compare_date) {
|
|
print "CALCDAYSINTERVAL: $compare_date[0] = $compare_date[1]: "
|
|
. DgS::printAr(DateTime::calcDaysInterval($compare_date[0], $compare_date[1])) . "<br>";
|
|
print "CALCDAYSINTERVAL(named): $compare_date[0] = $compare_date[1]: "
|
|
. DgS::printAr(DateTime::calcDaysInterval($compare_date[0], $compare_date[1], return_named:true)) . "<br>";
|
|
print "CALCDAYSINTERVAL(EXCLUDE END): $compare_date[0] = $compare_date[1]: "
|
|
. Dgs::printAr(DateTime::calcDaysInterval($compare_date[0], $compare_date[1], include_end_date:false));
|
|
print "CALCDAYSINTERVAL(EXCLUDE START): $compare_date[0] = $compare_date[1]: "
|
|
. Dgs::printAr(DateTime::calcDaysInterval($compare_date[0], $compare_date[1], exclude_start_date:true));
|
|
print "CALCDAYSINTERVAL(EXCLUDE END, EXCLUDE START): $compare_date[0] = $compare_date[1]: "
|
|
. Dgs::printAr(DateTime::calcDaysInterval(
|
|
$compare_date[0],
|
|
$compare_date[1],
|
|
include_end_date:false,
|
|
exclude_start_date:true
|
|
));
|
|
}
|
|
print "<hr>";
|
|
print "<h2>setWeekdayNameFromIsoDow</h2>";
|
|
// test date conversion
|
|
$dow = 2;
|
|
print "DOW[$dow]: " . DateTime::setWeekdayNameFromIsoDow($dow) . "<br>";
|
|
print "DOW[$dow],long: " . DateTime::setWeekdayNameFromIsoDow($dow, true) . "<br>";
|
|
$date = '2022-7-22';
|
|
print "DATE-dow[$date]: " . DateTime::setWeekdayNameFromDate($date) . "<br>";
|
|
print "DATE-dow[$date],long: " . DateTime::setWeekdayNameFromDate($date, true) . "<br>";
|
|
print "DOW-date[$date]: " . DateTime::setWeekdayNumberFromDate($date) . "<br>";
|
|
$dow = 11;
|
|
print "DOW[$dow];invalid: " . DateTime::setWeekdayNameFromIsoDow($dow) . "<br>";
|
|
print "DOW[$dow],long;invalid: " . DateTime::setWeekdayNameFromIsoDow($dow, true) . "<br>";
|
|
$date = '2022-70-242';
|
|
print "DATE-dow[$date];invalid: " . DateTime::setWeekdayNameFromDate($date) . "<br>";
|
|
print "DATE-dow[$date],long;invalid: " . DateTime::setWeekdayNameFromDate($date, true) . "<br>";
|
|
print "DOW-date[$date];invalid: " . DateTime::setWeekdayNumberFromDate($date) . "<br>";
|
|
|
|
print "<hr>";
|
|
print "<h2>dateRangeHasWeekend</h2>";
|
|
// check date range includes a weekend
|
|
$has_weekend_list = [
|
|
['2023-07-03', '2023-07-05'],
|
|
['2023-07-03', '2023-07-10'],
|
|
['2023-07-03', '2023-07-31'],
|
|
['2023-07-01', '2023-07-03'],
|
|
['2023-07-01', '2023-07-01'],
|
|
['2023-07-01', '2023-07-02'],
|
|
['2023-06-30', '2023-07-01'],
|
|
['2023-06-30', '2023-06-30'],
|
|
['2023-07-01', '2023-06-30'],
|
|
];
|
|
foreach ($has_weekend_list as $days) {
|
|
print "Has Weekend: " . $days[0] . " ~ " . $days[1] . ": "
|
|
. Dgs::prBl(DateTime::dateRangeHasWeekend($days[0], $days[1])) . "<br>";
|
|
}
|
|
|
|
print "</body></html>";
|
|
|
|
/**
|
|
* DEPREACTED, original rewrite, do not use
|
|
*
|
|
* update timeStringFormat with year and month support
|
|
*
|
|
* The following flags have to be set to be timeStringFormat compatible.
|
|
* Not that on seconds overflow this method will throw an exception, timeStringFormat returned -1s
|
|
* show_only_days: true,
|
|
* skip_zero: false,
|
|
* skip_last_zero: false,
|
|
* truncate_nanoseconds: true,
|
|
* truncate_zero_seconds_if_microseconds: false
|
|
*
|
|
* @param int|float $seconds Seconds to convert, maxium 6 decimals,
|
|
* else \UnexpectedValueException will be thrown
|
|
* if days too large or years too large \LengthException is thrown
|
|
* @param string $truncate_after [=''] Truncate after which time name, will not round, hard end
|
|
* values are parts names or interval short names (y, d, f, ...)
|
|
* if illegal value \UnexpectedValueException is thrown
|
|
* @param bool $natural_seperator [=false] use ',' and 'and', if off use space
|
|
* @param bool $name_space_seperator [=false] add a space between the number and the time name
|
|
* @param bool $show_microseconds [=true] show microseconds
|
|
* @param bool $short_time_name [=true] use the short time names (eg s instead of seconds)
|
|
* @param bool $skip_last_zero [=true] skip all trailing zero values, eg 5m 0s => 5m
|
|
* @param bool $skip_zero [=true] do not show zero values anywhere, eg 1h 0m 20s => 1h 20s
|
|
* @param bool $show_only_days [=false] do not show years or months, show only days
|
|
* if truncate after is set to year or month
|
|
* throws \UnexpectedValueException
|
|
* @param bool $auto_fix_microseconds [=false] if the micro seconds decimals are more than 6, round them
|
|
* on defaul throw \UnexpectedValueException
|
|
* @param bool $truncate_nanoseconds [=false] if microseconds decimals >3 then normal we show 123.4ms
|
|
* cut the .4 is set to true
|
|
* @param bool $truncate_zero_seconds_if_microseconds [=true] if we have 0.123 seconds then if true no seconds
|
|
* will be shown
|
|
* @return string
|
|
* @throws \UnexpectedValueException if seconds has more than 6 decimals
|
|
* if truncate has an illegal value
|
|
* if truncate is set to year or month and show_only_days is turned on
|
|
* @throws \LengthException if seconds is too large and show_days_only is selected and days is negetive
|
|
* or if years is negativ
|
|
*/
|
|
function intervalStringFormatDeprecated(
|
|
int|float $seconds,
|
|
string $truncate_after = '',
|
|
bool $natural_seperator = false,
|
|
bool $name_space_seperator = false,
|
|
bool $show_microseconds = true,
|
|
bool $short_time_name = true,
|
|
bool $skip_last_zero = true,
|
|
bool $skip_zero = true,
|
|
bool $show_only_days = false,
|
|
bool $auto_fix_microseconds = false,
|
|
bool $truncate_nanoseconds = false,
|
|
bool $truncate_zero_seconds_if_microseconds = true,
|
|
): string {
|
|
// auto fix long seconds, else \UnexpectedValueException will be thrown on error
|
|
// check if we have float and -> round to 6
|
|
if ($auto_fix_microseconds === true && is_float($seconds)) {
|
|
$seconds = round($seconds, 6);
|
|
}
|
|
// flag negative + set abs
|
|
$negative = $seconds < 0 ? '-' : '';
|
|
$seconds = abs($seconds);
|
|
// create base time
|
|
$date_now = new \DateTime("@0");
|
|
try {
|
|
$date_seconds = new \DateTime("@$seconds");
|
|
} catch (\Exception $e) {
|
|
throw new \UnexpectedValueException(
|
|
'Seconds value is invalid, too large or more than six decimals: ' . $seconds,
|
|
1,
|
|
$e
|
|
);
|
|
}
|
|
$interval = date_diff($date_now, $date_seconds);
|
|
// if show_only_days and negative but input postive alert that this has to be done in y/m/d ...
|
|
if ($interval->y < 0) {
|
|
throw new \LengthException('Input seconds value is too large for years output: ' . $seconds, 2);
|
|
} elseif ($interval->days < 0 && $show_only_days === true) {
|
|
throw new \LengthException('Input seconds value is too large for days output: ' . $seconds, 3);
|
|
}
|
|
// array order is important, small too large
|
|
$parts = [
|
|
'microseconds' => 'f',
|
|
'seconds' => 's', 'minutes' => 'i', 'hours' => 'h',
|
|
'days' => 'd', 'months' => 'm', 'years' => 'y',
|
|
];
|
|
$short_name = [
|
|
'years' => 'y', 'months' => 'm', 'days' => 'd',
|
|
'hours' => 'h', 'minutes' => 'm', 'seconds' => 's',
|
|
'microseconds' => 'ms'
|
|
];
|
|
$skip = false;
|
|
if (!empty($truncate_after)) {
|
|
// if truncate after not in key or value in parts
|
|
if (!in_array($truncate_after, array_keys($parts)) && !in_array($truncate_after, array_values($parts))) {
|
|
throw new \UnexpectedValueException(
|
|
'truncate_after has an invalid value: ' . $truncate_after,
|
|
4
|
|
);
|
|
}
|
|
// if truncate after is y or m and we have show_only_days, throw exception
|
|
if ($show_only_days === true && in_array($truncate_after, ['y', 'years', 'm', 'months'])) {
|
|
throw new \UnexpectedValueException(
|
|
'If show_only_days is turned on, the truncate_after cannot be years or months: '
|
|
. $truncate_after,
|
|
5
|
|
);
|
|
}
|
|
$skip = true;
|
|
}
|
|
$formatted = [];
|
|
$zero_list = [];
|
|
$zero_last_list = [];
|
|
$add_zero_seconds = false;
|
|
foreach ($parts as $time_name => $part) {
|
|
// end for micro seconds
|
|
if ($show_microseconds === false && $time_name == 'microseconds') {
|
|
continue;
|
|
}
|
|
// skip at this time position
|
|
if ($part == $truncate_after || $truncate_after == $time_name) {
|
|
$skip = false;
|
|
}
|
|
if ($skip === true) {
|
|
continue;
|
|
}
|
|
if ($show_only_days === true && $part == 'd') {
|
|
$value = $interval->days;
|
|
$skip = true;
|
|
} else {
|
|
/** @phan-suppress-next-line PhanUndeclaredProperty */
|
|
$value = $interval->$part;
|
|
}
|
|
if ($value == 0 && $skip_last_zero === true) {
|
|
continue;
|
|
}
|
|
// print "-> V: $value | $part, $time_name | I: " . is_int($value) . " | F: " . is_float($value)
|
|
// . " | " . ($value != 0 ? 'Not zero' : 'ZERO') . "<br>";
|
|
// var_dump($skip_last_zero);
|
|
if (
|
|
is_numeric($value) &&
|
|
($value != 0 || $skip_zero === false || $skip_last_zero === false)
|
|
) {
|
|
if ($part == 'f') {
|
|
if ($truncate_nanoseconds === true) {
|
|
$value = round($value, 3);
|
|
}
|
|
$value *= 1000;
|
|
// anything above that is nano seconds?
|
|
}
|
|
// on first hit turn off (full off)
|
|
if ($value) {
|
|
$skip_last_zero = null;
|
|
} elseif ($skip_last_zero === false) {
|
|
$zero_last_list[] = $part;
|
|
}
|
|
// build format
|
|
$format = "$value";
|
|
if ($name_space_seperator) {
|
|
$format .= " ";
|
|
}
|
|
if ($short_time_name) {
|
|
$format .= $short_name[$time_name];
|
|
} elseif ($value == 1) {
|
|
$format .= substr($time_name, 0, -1);
|
|
} else {
|
|
$format .= $time_name;
|
|
}
|
|
$formatted[] = $format;
|
|
}
|
|
// if we have 0 value, but only for skip zero condition
|
|
if ($skip_zero === false) {
|
|
if ($value == 0) {
|
|
$zero_list[] = $part;
|
|
} else {
|
|
$zero_list = [];
|
|
}
|
|
}
|
|
if (
|
|
$part == 's' && $value == 0 &&
|
|
$show_microseconds === true &&
|
|
$truncate_zero_seconds_if_microseconds === false
|
|
) {
|
|
$add_zero_seconds = true;
|
|
}
|
|
}
|
|
// if there is a zero list, strip that from the beginning, this is done always
|
|
if (count($zero_list)) {
|
|
// strip
|
|
$formatted = array_slice($formatted, 0, count($zero_list) * -1);
|
|
} elseif (count($zero_last_list) == count($formatted)) {
|
|
// if we have all skip empty last, then we do not have any value
|
|
$formatted = [];
|
|
}
|
|
$formatted = array_reverse($formatted);
|
|
// print "=> F: " . print_r($formatted, true)
|
|
// . " | Z: " . print_r($zero_list, true)
|
|
// . " | ZL: " . print_r($zero_last_list, true)
|
|
// . "<br>";
|
|
if (count($formatted) == 0) {
|
|
// if we have truncate on, then we assume nothing was found
|
|
$str = "0";
|
|
if ($name_space_seperator) {
|
|
$str .= " ";
|
|
}
|
|
// if truncate is on, we assume we found nothing
|
|
if (!empty($truncate_after)) {
|
|
if (in_array($truncate_after, array_values($parts))) {
|
|
$truncate_after = array_flip($parts)[$truncate_after];
|
|
}
|
|
$str .= ($short_time_name ? $short_name[$truncate_after] : $truncate_after);
|
|
} else {
|
|
$str .= ($short_time_name ? $short_name['seconds'] : 'seconds');
|
|
}
|
|
return $str;
|
|
} elseif (count($formatted) == 1) {
|
|
return $negative .
|
|
($add_zero_seconds ?
|
|
'0'
|
|
. ($name_space_seperator ? ' ' : '')
|
|
. ($short_time_name ? $short_name['seconds'] : 'seconds')
|
|
. ' '
|
|
: ''
|
|
)
|
|
. $formatted[0];
|
|
} elseif ($natural_seperator === false) {
|
|
return $negative . implode(' ', $formatted);
|
|
} else {
|
|
$str = implode(', ', array_slice($formatted, 0, -1));
|
|
if (!empty($formatted[count($formatted) - 1])) {
|
|
$str .= ' and ' . $formatted[count($formatted) - 1];
|
|
}
|
|
return $negative . $str;
|
|
}
|
|
}
|
|
|
|
// __END__
|