From 47b878b031d0c39e48dc50ba01dcfddcb7bddac3 Mon Sep 17 00:00:00 2001 From: gtbu Date: Sat, 1 Mar 2025 20:41:04 +0100 Subject: [PATCH] new strftime-emulation and category new strftime-emulator with intltime // new field category added under rename/details in pagemanager. --- include/Page/Rename.php | 13 +- include/admin/Configuration.php | 1 + include/common.php | 4 +- include/install/Tools.php | 3 +- include/thirdparty/time/strftime-8.1.php | 220 ------------ include/thirdparty/time/strftime-bo-mod.php | 190 +++++++++++ include/thirdparty/time/strftime.php | 359 ++++++++++---------- include/tool.php | 5 +- 8 files changed, 394 insertions(+), 401 deletions(-) delete mode 100644 include/thirdparty/time/strftime-8.1.php create mode 100644 include/thirdparty/time/strftime-bo-mod.php diff --git a/include/Page/Rename.php b/include/Page/Rename.php index 8eb6d12..7f84d28 100644 --- a/include/Page/Rename.php +++ b/include/Page/Rename.php @@ -31,6 +31,7 @@ namespace gp\Page{ 'keywords' => '', 'description' => '', 'rel' => '', + 'category' => '', ); if( empty($_REQUEST['new_title']) ){ @@ -69,7 +70,6 @@ namespace gp\Page{ //slug (title) $attr = ''; $class = 'new_title'; - if( $title == \gp\admin\Tools::LabelToSlug($label) ){ //$attr = 'disabled="disabled" '; $attr = 'readonly="readonly"" '; @@ -80,8 +80,7 @@ namespace gp\Page{ self::ToggleSync($attr); echo ''; - - + //browser title defaults to label $attr = ''; $class = 'browser_title'; @@ -99,6 +98,13 @@ namespace gp\Page{ echo ''; + //category : wird in data site config.php definiert und in pages.php eingetragen / admin/configuration.php 36 -- include install tools 242 + $category = $title_info['category']; + self::FormLabel('category',$title_info['category']); + echo ''; + echo ''; + + //meta keywords self::FormLabel('keywords',$title_info['keywords']); echo ''; @@ -246,6 +252,7 @@ namespace gp\Page{ self::SetInfo($title_info, 'browser_title'); self::SetInfo($title_info, 'keywords'); self::SetInfo($title_info, 'description'); + self::SetInfo($title_info, 'category'); self::SetRobots($title_info); diff --git a/include/admin/Configuration.php b/include/admin/Configuration.php index 5f80bdf..f1ea4c8 100644 --- a/include/admin/Configuration.php +++ b/include/admin/Configuration.php @@ -33,6 +33,7 @@ class Configuration extends \gp\special\Base{ /* General Settings */ 'general_settings' => false, 'title' => '', + 'category' => '', 'keywords' => '', 'desc' => 'textarea', diff --git a/include/common.php b/include/common.php index 89e1a83..4f90810 100644 --- a/include/common.php +++ b/include/common.php @@ -1,7 +1,6 @@ - * https://github.com/alphp/strftime MIT - */ - function strftime (string $format, $timestamp = null, ?string $locale = null) : string { - if (!($timestamp instanceof DateTimeInterface)) { - $timestamp = is_int($timestamp) ? '@' . $timestamp : (string) $timestamp; - - try { - $timestamp = new DateTime($timestamp); - } catch (Exception $e) { - throw new InvalidArgumentException('$timestamp argument is neither a valid UNIX timestamp, a valid date-time string or a DateTime object.', 0, $e); - } - } - - $timestamp->setTimezone(new DateTimeZone(date_default_timezone_get())); - - if (empty($locale)) { - // get current locale - $locale = setlocale(LC_TIME, '0'); - } - // remove trailing part not supported by ext-intl locale - $locale = preg_replace('/[^\w-].*$/', '', $locale); - - $intl_formats = [ - '%a' => 'EEE', // An abbreviated textual representation of the day Sun through Sat - '%A' => 'EEEE', // A full textual representation of the day Sunday through Saturday - '%b' => 'MMM', // Abbreviated month name, based on the locale Jan through Dec - '%B' => 'MMMM', // Full month name, based on the locale January through December - '%h' => 'MMM', // Abbreviated month name, based on the locale (an alias of %b) Jan through Dec - ]; - - $intl_formatter = function (DateTimeInterface $timestamp, string $format) use ($intl_formats, $locale) { - $tz = $timestamp->getTimezone(); - $date_type = IntlDateFormatter::FULL; - $time_type = IntlDateFormatter::FULL; - $pattern = ''; - - switch ($format) { - // %c = Preferred date and time stamp based on locale - // Example: Tue Feb 5 00:45:10 2009 for February 5, 2009 at 12:45:10 AM - case '%c': - $date_type = IntlDateFormatter::LONG; - $time_type = IntlDateFormatter::SHORT; - break; - - // %x = Preferred date representation based on locale, without the time - // Example: 02/05/09 for February 5, 2009 - case '%x': - $date_type = IntlDateFormatter::SHORT; - $time_type = IntlDateFormatter::NONE; - break; - - // Localized time format - case '%X': - $date_type = IntlDateFormatter::NONE; - $time_type = IntlDateFormatter::MEDIUM; - break; - - default: - $pattern = $intl_formats[$format]; - } - - // In October 1582, the Gregorian calendar replaced the Julian in much of Europe, and - // the 4th October was followed by the 15th October. - // ICU (including IntlDateFormattter) interprets and formats dates based on this cutover. - // Posix (including strftime) and timelib (including DateTimeImmutable) instead use - // a "proleptic Gregorian calendar" - they pretend the Gregorian calendar has existed forever. - // This leads to the same instants in time, as expressed in Unix time, having different representations - // in formatted strings. - // To adjust for this, a custom calendar can be supplied with a cutover date arbitrarily far in the past. - $calendar = IntlGregorianCalendar::createInstance(); - $calendar->setGregorianChange(PHP_INT_MIN); - - return (new IntlDateFormatter($locale, $date_type, $time_type, $tz, $calendar, $pattern))->format($timestamp); - }; - - // Same order as https://www.php.net/manual/en/function.strftime.php - $translation_table = [ - // Day - '%a' => $intl_formatter, - '%A' => $intl_formatter, - '%d' => 'd', - '%e' => function ($timestamp) { - return sprintf('% 2u', $timestamp->format('j')); - }, - '%j' => function ($timestamp) { - // Day number in year, 001 to 366 - return sprintf('%03d', $timestamp->format('z')+1); - }, - '%u' => 'N', - '%w' => 'w', - - // Week - '%U' => function ($timestamp) { - // Number of weeks between date and first Sunday of year - $day = new DateTime(sprintf('%d-01 Sunday', $timestamp->format('Y'))); - return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7); - }, - '%V' => 'W', - '%W' => function ($timestamp) { - // Number of weeks between date and first Monday of year - $day = new DateTime(sprintf('%d-01 Monday', $timestamp->format('Y'))); - return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7); - }, - - // Month - '%b' => $intl_formatter, - '%B' => $intl_formatter, - '%h' => $intl_formatter, - '%m' => 'm', - - // Year - '%C' => function ($timestamp) { - // Century (-1): 19 for 20th century - return floor($timestamp->format('Y') / 100); - }, - '%g' => function ($timestamp) { - return substr($timestamp->format('o'), -2); - }, - '%G' => 'o', - '%y' => 'y', - '%Y' => 'Y', - - // Time - '%H' => 'H', - '%k' => function ($timestamp) { - return sprintf('% 2u', $timestamp->format('G')); - }, - '%I' => 'h', - '%l' => function ($timestamp) { - return sprintf('% 2u', $timestamp->format('g')); - }, - '%M' => 'i', - '%p' => 'A', // AM PM (this is reversed on purpose!) - '%P' => 'a', // am pm - '%r' => 'h:i:s A', // %I:%M:%S %p - '%R' => 'H:i', // %H:%M - '%S' => 's', - '%T' => 'H:i:s', // %H:%M:%S - '%X' => $intl_formatter, // Preferred time representation based on locale, without the date - - // Timezone - '%z' => 'O', - '%Z' => 'T', - - // Time and Date Stamps - '%c' => $intl_formatter, - '%D' => 'm/d/Y', - '%F' => 'Y-m-d', - '%s' => 'U', - '%x' => $intl_formatter, - ]; - - $out = preg_replace_callback('/(?format($replace); - } - else { - $result = $replace($timestamp, $pattern); - } - - switch ($prefix) { - case '_': - // replace leading zeros with spaces but keep last char if also zero - return preg_replace('/\G0(?=.)/', ' ', $result); - case '#': - case '-': - // remove leading zeros but keep last char if also zero - return preg_replace('/^0+(?=.)/', '', $result); - } - - return $result; - }, $format); - - $out = str_replace('%%', '%', $out); - return $out; - } diff --git a/include/thirdparty/time/strftime-bo-mod.php b/include/thirdparty/time/strftime-bo-mod.php new file mode 100644 index 0000000..a952444 --- /dev/null +++ b/include/thirdparty/time/strftime-bo-mod.php @@ -0,0 +1,190 @@ + + */ +function strftime(string $format, $timestamp = null, ?string $locale = null): string +{ + if (null === $timestamp) { + $timestamp = new \DateTime; + } + elseif (is_numeric($timestamp)) { + $timestamp = date_create('@' . $timestamp); + + if ($timestamp) { + $timestamp->setTimezone(new \DateTimezone(date_default_timezone_get())); + } + } + elseif (is_string($timestamp)) { + $timestamp = date_create($timestamp); + } + + if (!($timestamp instanceof \DateTimeInterface)) { + throw new \InvalidArgumentException('$timestamp argument is neither a valid UNIX timestamp, a valid date-time string or a DateTime object.'); + } + + $locale = substr((string) $locale, 0, 5); + + $intl_formats = [ + '%a' => 'EEE', // An abbreviated textual representation of the day Sun through Sat + '%A' => 'EEEE', // A full textual representation of the day Sunday through Saturday + '%b' => 'MMM', // Abbreviated month name, based on the locale Jan through Dec + '%B' => 'MMMM', // Full month name, based on the locale January through December + '%h' => 'MMM', // Abbreviated month name, based on the locale (an alias of %b) Jan through Dec + ]; + + $intl_formatter = function (\DateTimeInterface $timestamp, string $format) use ($intl_formats, $locale) { + $tz = $timestamp->getTimezone(); + $date_type = \IntlDateFormatter::FULL; + $time_type = \IntlDateFormatter::FULL; + $pattern = ''; + + // %c = Preferred date and time stamp based on locale + // Example: Tue Feb 5 00:45:10 2009 for February 5, 2009 at 12:45:10 AM + if ($format == '%c') { + $date_type = \IntlDateFormatter::LONG; + $time_type = \IntlDateFormatter::SHORT; + } + // %x = Preferred date representation based on locale, without the time + // Example: 02/05/09 for February 5, 2009 + elseif ($format == '%x') { + $date_type = \IntlDateFormatter::SHORT; + $time_type = \IntlDateFormatter::NONE; + } + // Localized time format + elseif ($format == '%X') { + $date_type = \IntlDateFormatter::NONE; + $time_type = \IntlDateFormatter::MEDIUM; + } + else { + $pattern = $intl_formats[$format]; + } + + return (new \IntlDateFormatter($locale, $date_type, $time_type, $tz, null, $pattern))->format($timestamp); + }; + + // Same order as https://www.php.net/manual/en/function.strftime.php + $translation_table = [ + // Day + '%a' => $intl_formatter, + '%A' => $intl_formatter, + '%d' => 'd', + '%e' => function ($timestamp) { + return sprintf('% 2u', $timestamp->format('j')); + }, + '%j' => function ($timestamp) { + // Day number in year, 001 to 366 + return sprintf('%03d', $timestamp->format('z')+1); + }, + '%u' => 'N', + '%w' => 'w', + + // Week + '%U' => function ($timestamp) { + // Number of weeks between date and first Sunday of year + $day = new \DateTime(sprintf('%d-01 Sunday', $timestamp->format('Y'))); + return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7); + }, + '%V' => 'W', + '%W' => function ($timestamp) { + // Number of weeks between date and first Monday of year + $day = new \DateTime(sprintf('%d-01 Monday', $timestamp->format('Y'))); + return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7); + }, + + // Month + '%b' => $intl_formatter, + '%B' => $intl_formatter, + '%h' => $intl_formatter, + '%m' => 'm', + + // Year + '%C' => function ($timestamp) { + // Century (-1): 19 for 20th century + return floor($timestamp->format('Y') / 100); + }, + '%g' => function ($timestamp) { + return substr($timestamp->format('o'), -2); + }, + '%G' => 'o', + '%y' => 'y', + '%Y' => 'Y', + + // Time + '%H' => 'H', + '%k' => function ($timestamp) { + return sprintf('% 2u', $timestamp->format('G')); + }, + '%I' => 'h', + '%l' => function ($timestamp) { + return sprintf('% 2u', $timestamp->format('g')); + }, + '%M' => 'i', + '%p' => 'A', // AM PM (this is reversed on purpose!) + '%P' => 'a', // am pm + '%r' => 'h:i:s A', // %I:%M:%S %p + '%R' => 'H:i', // %H:%M + '%S' => 's', + '%T' => 'H:i:s', // %H:%M:%S + '%X' => $intl_formatter, // Preferred time representation based on locale, without the date + + // Timezone + '%z' => 'O', + '%Z' => 'T', + + // Time and Date Stamps + '%c' => $intl_formatter, + '%D' => 'm/d/Y', + '%F' => 'Y-m-d', + '%s' => 'U', + '%x' => $intl_formatter, + ]; + + $out = preg_replace_callback('/(?format($replace); + } + else { + return $replace($timestamp, $match[1]); + } + }, $format); + + $out = str_replace('%%', '%', $out); + return $out; +} diff --git a/include/thirdparty/time/strftime.php b/include/thirdparty/time/strftime.php index a952444..921158c 100644 --- a/include/thirdparty/time/strftime.php +++ b/include/thirdparty/time/strftime.php @@ -1,190 +1,201 @@ + * @param string $format The format string. See https://www.php.net/manual/en/function.strftime.php for details. + * @param int|string|DateTimeInterface|null $timestamp (Optional) The timestamp to format. If null, uses the current time. + * @param string|null $locale (Optional) The locale to use. If null, uses the default locale. + * @param string|null $timezone (Optional) The timezone to use. If null, uses the default timezone. + * @return string|false The formatted string, or false on failure. + * @throws InvalidArgumentException */ -function strftime(string $format, $timestamp = null, ?string $locale = null): string +function strftime(string $format, int|string|DateTimeInterface|null $timestamp = null, ?string $locale = null, ?string $timezone = null): string|false { - if (null === $timestamp) { - $timestamp = new \DateTime; - } - elseif (is_numeric($timestamp)) { - $timestamp = date_create('@' . $timestamp); + if (!extension_loaded('intl')) { + trigger_error('The intl extension is not loaded.', E_USER_WARNING); + return false; + } - if ($timestamp) { - $timestamp->setTimezone(new \DateTimezone(date_default_timezone_get())); - } - } - elseif (is_string($timestamp)) { - $timestamp = date_create($timestamp); - } + // Handle Timestamp Input and Create DateTime Object + try { + if ($timestamp === null) { + $dateTime = new DateTime(); + } elseif (is_numeric($timestamp)) { + $dateTime = new DateTime('@' . $timestamp); + $dateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); + } elseif (is_string($timestamp)) { + $dateTime = new DateTime($timestamp); + } elseif ($timestamp instanceof DateTimeInterface) { + $dateTime = $timestamp; + } else { + throw new InvalidArgumentException('$timestamp argument is not a valid date-time string nor a DateTime object nor a valid UNIX timestamp.'); + } + } catch (\Exception $e) { + throw new InvalidArgumentException('Invalid timestamp format', 0, $e); + } - if (!($timestamp instanceof \DateTimeInterface)) { - throw new \InvalidArgumentException('$timestamp argument is neither a valid UNIX timestamp, a valid date-time string or a DateTime object.'); - } + // Set Locale and Timezone (use defaults if not provided) + $locale = $locale ?? \Locale::getDefault(); + $timezone = $timezone ?? date_default_timezone_get(); + $timeZoneObject = new DateTimeZone($timezone); + $dateTime->setTimezone($timeZoneObject); - $locale = substr((string) $locale, 0, 5); + // Format Map: strftime to ICU + $formatMap = [ + '%a' => 'EEE', // Abbreviated weekday name + '%A' => 'EEEE', // Full weekday name + '%b' => 'MMM', // Abbreviated month name + '%B' => 'MMMM', // Full month name + '%c' => 'EEE MMM dd HH:mm:ss yyyy', // Preferred date and time representation (locale-dependent) + '%C' => null, // Century number (year/100, truncated to integer) + '%d' => 'dd', // Day of the month as a decimal number (01-31) + '%D' => 'MM/dd/yy', // Short MM/DD/YY date + '%e' => 'd', // Day of the month as a decimal number (1-31); a single digit is preceded by a space + '%F' => 'yyyy-MM-dd', // ISO 8601 date format (YYYY-MM-DD) + '%g' => 'yy', // The ISO 8601 week-based year without the century (00-99) (approximation) + '%G' => 'yyyy', // The ISO 8601 week-based year with century + '%h' => 'MMM', // Same as %b + '%H' => 'HH', // Hour as a decimal number (00-23) + '%I' => 'hh', // Hour as a decimal number (01-12) + '%j' => null, // Day of the year as a decimal number (001-366) + '%m' => 'MM', // Month as a decimal number (01-12) + '%M' => 'mm', // Minute as a decimal number (00-59) + '%n' => "\n", // A newline character + '%p' => 'a', // AM or PM + '%P' => null, // am or pm (lowercase) + '%r' => 'hh:mm:ss a', // AM/PM time format + '%R' => 'HH:mm', // 24-hour HH:MM time format + '%s' => null, // Number of seconds since the Epoch + '%S' => 'ss', // Second as a decimal number (00-60) + '%t' => "\t", // A tab character + '%T' => 'HH:mm:ss', // 24-hour time format + '%u' => null, // ISO 8601 weekday as number with Monday as 1 + '%U' => null, // Week number of the current year (Sunday as first day) + '%V' => null, // ISO 8601 week number + '%w' => null, // Weekday as a decimal number (0-6), with Sunday as 0 + '%W' => null, // Week number of the current year, starting with the first Monday as the first week + '%x' => 'MM/dd/yyyy', // Preferred date representation (locale-dependent) + '%X' => 'HH:mm:ss', // Preferred time representation (locale-dependent) + '%y' => 'yy', // Year without century (00-99) + '%Y' => 'yyyy', // Year with century + '%z' => 'ZZZZ', // Numeric timezone offset. E.g., -0800 + '%Z' => 'z', // Timezone abbreviation + '%%' => '%', // A literal '%' character + '%k' => null, // Hour in 24-hour format, space-padded + '%l' => null, // Hour in 12-hour format, space-padded + ]; - $intl_formats = [ - '%a' => 'EEE', // An abbreviated textual representation of the day Sun through Sat - '%A' => 'EEEE', // A full textual representation of the day Sunday through Saturday - '%b' => 'MMM', // Abbreviated month name, based on the locale Jan through Dec - '%B' => 'MMMM', // Full month name, based on the locale January through December - '%h' => 'MMM', // Abbreviated month name, based on the locale (an alias of %b) Jan through Dec - ]; + // Build ICU Format String + $icuFormat = ''; + $len = strlen($format); - $intl_formatter = function (\DateTimeInterface $timestamp, string $format) use ($intl_formats, $locale) { - $tz = $timestamp->getTimezone(); - $date_type = \IntlDateFormatter::FULL; - $time_type = \IntlDateFormatter::FULL; - $pattern = ''; + for ($i = 0; $i < $len; $i++) { + if ($format[$i] == '%') { + $i++; + if (!isset($format[$i])) { + return false; // Invalid format. Trailing %. + } - // %c = Preferred date and time stamp based on locale - // Example: Tue Feb 5 00:45:10 2009 for February 5, 2009 at 12:45:10 AM - if ($format == '%c') { - $date_type = \IntlDateFormatter::LONG; - $time_type = \IntlDateFormatter::SHORT; - } - // %x = Preferred date representation based on locale, without the time - // Example: 02/05/09 for February 5, 2009 - elseif ($format == '%x') { - $date_type = \IntlDateFormatter::SHORT; - $time_type = \IntlDateFormatter::NONE; - } - // Localized time format - elseif ($format == '%X') { - $date_type = \IntlDateFormatter::NONE; - $time_type = \IntlDateFormatter::MEDIUM; - } - else { - $pattern = $intl_formats[$format]; - } + $key = '%' . $format[$i]; + if (isset($formatMap[$key])) { + if ($formatMap[$key] === null) { + // Handle cases where a direct mapping isn't possible + switch ($key) { + case '%C': + $icuFormat .= floor($dateTime->format('Y') / 100); + break; + case '%j': + $icuFormat .= sprintf('%03d', (int)$dateTime->format('z') + 1); + break; + case '%s': + $icuFormat .= $dateTime->getTimestamp(); + break; + case '%k': + $icuFormat .= sprintf('% 2u', $dateTime->format('G')); // Hour in 24-hour format, space-padded + break; + case '%l': + $icuFormat .= sprintf('% 2u', $dateTime->format('g')); // Hour in 12-hour format, space-padded + break; + case '%u': // ISO 8601 weekday as number with Monday as 1 + $dayOfWeek = (int)$dateTime->format('N'); + $icuFormat .= $dayOfWeek; + break; + case '%w': // Weekday as a decimal number (0-6), with Sunday as 0 + $icuFormat .= $dateTime->format('w'); + break; + case '%U': // Week number of the current year as a decimal number, starting with the first Sunday as the first week + case '%W': // Week number of the current year as a decimal number, starting with the first Monday as the first week + case '%V': // The ISO 8601 week number (01-53) + $calendar = IntlCalendar::createInstance($timeZoneObject, $locale); + $calendar->setTime($dateTime->getTimestamp() * 1000); // IntlCalendar uses milliseconds - return (new \IntlDateFormatter($locale, $date_type, $time_type, $tz, null, $pattern))->format($timestamp); - }; + if ($key == '%U') { + $icuFormat .= $calendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR); + } elseif ($key == '%W') { + $calendar->setMinimalDaysInFirstWeek(4); // ISO 8601 + $calendar->setFirstDayOfWeek(IntlCalendar::MONDAY); // ISO 8601 + $icuFormat .= $calendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR); - // Same order as https://www.php.net/manual/en/function.strftime.php - $translation_table = [ - // Day - '%a' => $intl_formatter, - '%A' => $intl_formatter, - '%d' => 'd', - '%e' => function ($timestamp) { - return sprintf('% 2u', $timestamp->format('j')); - }, - '%j' => function ($timestamp) { - // Day number in year, 001 to 366 - return sprintf('%03d', $timestamp->format('z')+1); - }, - '%u' => 'N', - '%w' => 'w', + } else { // %V + $calendar->setMinimalDaysInFirstWeek(4); // ISO 8601 + $calendar->setFirstDayOfWeek(IntlCalendar::MONDAY); // ISO 8601 + $icuFormat .= sprintf("%02d", $calendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR)); //format to 2 digits + } + break; + case '%P': + $amPm = $dateTime->format('a'); + $icuFormat .= strtolower($amPm); + break; + default: + return false; // Indicate unsupported format + } + } else { + $icuFormat .= $formatMap[$key]; + } + } else { + return false; // Unknown format code. + } + } else { + $icuFormat .= $format[$i]; + } + } - // Week - '%U' => function ($timestamp) { - // Number of weeks between date and first Sunday of year - $day = new \DateTime(sprintf('%d-01 Sunday', $timestamp->format('Y'))); - return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7); - }, - '%V' => 'W', - '%W' => function ($timestamp) { - // Number of weeks between date and first Monday of year - $day = new \DateTime(sprintf('%d-01 Monday', $timestamp->format('Y'))); - return sprintf('%02u', 1 + ($timestamp->format('z') - $day->format('z')) / 7); - }, + try { + $formatter = new IntlDateFormatter( + $locale, + IntlDateFormatter::FULL, + IntlDateFormatter::FULL, + $timeZoneObject, + IntlDateFormatter::GREGORIAN, + $icuFormat + ); - // Month - '%b' => $intl_formatter, - '%B' => $intl_formatter, - '%h' => $intl_formatter, - '%m' => 'm', - - // Year - '%C' => function ($timestamp) { - // Century (-1): 19 for 20th century - return floor($timestamp->format('Y') / 100); - }, - '%g' => function ($timestamp) { - return substr($timestamp->format('o'), -2); - }, - '%G' => 'o', - '%y' => 'y', - '%Y' => 'Y', - - // Time - '%H' => 'H', - '%k' => function ($timestamp) { - return sprintf('% 2u', $timestamp->format('G')); - }, - '%I' => 'h', - '%l' => function ($timestamp) { - return sprintf('% 2u', $timestamp->format('g')); - }, - '%M' => 'i', - '%p' => 'A', // AM PM (this is reversed on purpose!) - '%P' => 'a', // am pm - '%r' => 'h:i:s A', // %I:%M:%S %p - '%R' => 'H:i', // %H:%M - '%S' => 's', - '%T' => 'H:i:s', // %H:%M:%S - '%X' => $intl_formatter, // Preferred time representation based on locale, without the date - - // Timezone - '%z' => 'O', - '%Z' => 'T', - - // Time and Date Stamps - '%c' => $intl_formatter, - '%D' => 'm/d/Y', - '%F' => 'Y-m-d', - '%s' => 'U', - '%x' => $intl_formatter, - ]; - - $out = preg_replace_callback('/(?format($replace); - } - else { - return $replace($timestamp, $match[1]); - } - }, $format); - - $out = str_replace('%%', '%', $out); - return $out; -} + return $formatter->format($dateTime); + } catch (\Exception $e) { + // Handle invalid locale or timezone + error_log("IntlDateFormatter exception: " . $e->getMessage()); // Log the error + return false; + } +} \ No newline at end of file diff --git a/include/tool.php b/include/tool.php index a1c3045..60a0b07 100644 --- a/include/tool.php +++ b/include/tool.php @@ -2,7 +2,10 @@ namespace gp{ - use function \PHP81_BC\strftime; + +use intltime; +use function \intltime\strftime; + defined('is_running') or die('Not an entry point...'); class tool{