PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Services / DateTime / DateTime.php

DateTime.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Services/DateTime/DateTime.php

169 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\DateTime;
4
5 use DateTimeInterface;
6 use DateTimeZone;
7
8 class DateTime extends \FluentCart\Framework\Support\DateTime
9 {
10
11 use CanExtractTimeZone;
12
13 /**
14 * Create a new DateTime Object with current GMT/UTC time
15 *
16 * @return static
17 */
18 public static function gmtNow()
19 {
20
21 return static::create('now', new DateTimeZone('UTC'));
22 }
23
24
25 public static function now($tz = null)
26 {
27 return static::create('now', new DateTimeZone('UTC'));
28 }
29
30 /**
31 * Convert any datetime to GMT/UTC
32 *
33 * @param string|DateTimeInterface|null $datetime The datetime to convert (defaults to current instance)
34 * @return static
35 */
36 public static function anyTimeToGmt($datetime = null, $fromTz = null)
37 {
38 if (is_null($datetime)) {
39 $datetime = static::now();
40 return (clone $datetime)->setTimezone(new DateTimeZone('UTC'));
41 }
42
43 // If it's already a Carbon or DateTime instance
44 if ($datetime instanceof \DateTimeInterface) {
45 $dt = clone $datetime;
46
47 // If fromTz is specified and the datetime doesn't have timezone info, set it
48 if ($fromTz && $dt->getTimezone()->getName() === 'UTC' && $fromTz !== 'UTC') {
49 $dt = $dt->setTimezone(static::resolveTimezone($fromTz));
50 }
51
52 return $dt->setTimezone(new \DateTimeZone('UTC'));
53 }
54
55 // If it's a Unix timestamp (int or numeric string)
56 if (is_numeric($datetime)) {
57 $dt = new static('@' . (int)$datetime);
58 return $dt->setTimezone(new \DateTimeZone('UTC'));
59 }
60
61 // If it's a string, parse it with optional timezone context
62 if (is_string($datetime)) {
63 $dt = static::parse($datetime);
64
65 // If fromTz is provided and the parsed string doesn't contain timezone info
66 if ($fromTz && !preg_match('/[+-]\d{2}:?\d{2}$|Z$|[A-Z]{3,4}$/i', trim($datetime))) {
67 // Create a new datetime in the specified timezone
68 $dt = static::createFromFormat('Y-m-d H:i:s', $dt->format('Y-m-d H:i:s'), static::resolveTimezone($fromTz));
69 }
70
71 return $dt->setTimezone(new \DateTimeZone('UTC'));
72 }
73
74 throw new \InvalidArgumentException(esc_html__('Invalid datetime format.', 'fluent-cart'));
75 }
76
77 public static function gmdate($datetime = null, $fromTz = null)
78 {
79 return static::anyTimeToGmt($datetime, $fromTz);
80 }
81
82
83 /**
84 * Convert a GMT/UTC datetime to the given timezone
85 *
86 * @param string|\DateTimeInterface|null $datetime The datetime to convert (defaults to now in UTC)
87 * @param string|null $timezone Target timezone (defaults to site timezone)
88 * @return static
89 */
90 public static function gmtToTimezone($datetime = null, $timezone = null): DateTime
91 {
92 if (!$timezone instanceof \DateTimeZone) {
93 $timezone = static::resolveTimezone($timezone);
94 }
95
96
97 if (is_null($datetime)) {
98 $datetime = static::now(); // returns UTC time
99 }
100
101 if ($datetime instanceof \DateTimeInterface) {
102 return (clone $datetime)->setTimezone($timezone);
103 }
104
105 if (is_numeric($datetime)) {
106 $dt = new static('@' . (int)$datetime);
107 return $dt->setTimezone($timezone);
108 }
109
110 if (is_string($datetime)) {
111 $dt = static::parse($datetime, new \DateTimeZone('UTC')); // assume UTC
112 return $dt->setTimezone($timezone);
113 }
114 throw new \InvalidArgumentException(esc_html__('Invalid datetime format.', 'fluent-cart'));
115
116 }
117
118
119 /**
120 * Safely resolve a timezone string to a DateTimeZone object.
121 *
122 * PHP 8.4 throws on deprecated aliases like Asia/Saigon, so we validate
123 * with timezone_open() before constructing. Old orders may carry such aliases
124 * from the browser-captured user_tz stored in order config at checkout time.
125 * Falls back to the supplied $fallback, or wp_timezone() if none given.
126 */
127 private static function resolveTimezone($timezone, $fallback = null): \DateTimeZone
128 {
129 if ($timezone instanceof \DateTimeZone) {
130 return $timezone;
131 }
132 if (is_string($timezone) && $timezone !== '' && @timezone_open($timezone) !== false) {
133 return new \DateTimeZone($timezone);
134 }
135 return ($fallback instanceof \DateTimeZone) ? $fallback : wp_timezone();
136 }
137
138 public function getDefaultTimezone()
139 {
140 return new DateTimeZone('UTC');
141 }
142
143
144 public static function parse($datetimeString, $timezone = null)
145 {
146 $hasTimezone = preg_match('/([Zz]|[+-]\d{2}:\d{2}|[+-]\d{4})/', $datetimeString);
147
148 try {
149 if ($hasTimezone) {
150 // Use the timezone embedded in the string
151 $dt = new \DateTimeImmutable($datetimeString);
152 } else {
153 $tz = $timezone instanceof \DateTimeZone
154 ? $timezone
155 : ($timezone ? static::resolveTimezone($timezone, new \DateTimeZone('UTC')) : new DateTimeZone('UTC'));
156
157 $dt = new \DateTimeImmutable($datetimeString, $tz);
158 }
159
160 return new static($dt->format('Y-m-d H:i:s'), $dt->getTimezone());
161 } catch (\Exception $e) {
162 throw new \InvalidArgumentException(
163 esc_html__('Unable to parse datetime:', 'fluent-cart') . ' ' . esc_html($e->getMessage())
164 );
165 }
166 }
167
168 }
169