Skip to content

Commit aef422e

Browse files
committed
Add string and clock methods and tests
1 parent 173530e commit aef422e

File tree

7 files changed

+1114
-249
lines changed

7 files changed

+1114
-249
lines changed

src/Format/Clock.php

Lines changed: 248 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,20 @@
99

1010
namespace MaplePHP\DTO\Format;
1111

12+
use DateTime;
13+
use DateTimeImmutable;
14+
use DateTimeInterface;
15+
use DateTimeZone;
1216
use Exception;
1317
use IntlDateFormatter;
1418
use InvalidArgumentException;
1519

1620
final class Clock extends FormatAbstract implements FormatInterface
1721
{
1822
static protected ?string $defaultLocale = 'en';
23+
24+
static protected string|DateTimeZone|null $defaultTimezone = null;
25+
1926
protected ?string $locale = null;
2027
protected array $parts = [];
2128

@@ -30,8 +37,11 @@ public function __construct(mixed $value)
3037
if (is_array($value) || is_object($value)) {
3138
throw new InvalidArgumentException("Is expecting a string or a convertable string value.", 1);
3239
}
33-
34-
parent::__construct(new \DateTime($value));
40+
$date = new DateTime($value);
41+
if(!is_null(self::$defaultTimezone)) {
42+
$date->setTimezone(self::$defaultTimezone);
43+
}
44+
parent::__construct($date);
3545
}
3646

3747
/**
@@ -61,16 +71,28 @@ public function getLocale(): ?string
6171
* @param string $localeCode
6272
* @return $this
6373
*/
64-
public function setLanguage(string $localeCode): self
74+
public function setLocale(string $localeCode): self
6575
{
6676
$this->locale = $localeCode;
6777
return $this;
6878
}
6979

70-
// Alias to setLanguage
71-
public function setLocale(string $localeCode): self
80+
// Alias to setLocale
81+
public function setLanguage(string $localeCode): self
7282
{
73-
return $this->setLanguage($localeCode);
83+
return $this->setLocale($localeCode);
84+
}
85+
86+
/**
87+
* Set default timezone
88+
*
89+
* @param string|DateTimeZone $timezone
90+
* @return void
91+
* @throws \DateInvalidTimeZoneException
92+
*/
93+
static public function setDefaultTimezone(string|DateTimeZone $timezone): void
94+
{
95+
self::$defaultTimezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
7496
}
7597

7698
/**
@@ -79,15 +101,15 @@ public function setLocale(string $localeCode): self
79101
* @param string $localeCode
80102
* @return void
81103
*/
82-
static public function setDefaultLanguage(string $localeCode): void
104+
static public function setDefaultLocale(string $localeCode): void
83105
{
84106
self::$defaultLocale = $localeCode;
85107
}
86108

87-
// Alias to setDefaultLanguage
88-
static public function setDefaultLocale(string $localeCode): void
109+
// Alias to setDefaultLocale
110+
static public function setDefaultLanguage(string $localeCode): void
89111
{
90-
self::setDefaultLanguage($localeCode);
112+
self::setDefaultLocale($localeCode);
91113
}
92114

93115
/**
@@ -137,6 +159,220 @@ public function date(): string
137159
return $this->raw->format('Y-m-d');
138160
}
139161

162+
/**
163+
* Get hour and minutes
164+
*
165+
* @return string
166+
*/
167+
public function time(): string
168+
{
169+
return $this->raw->format('H:i');
170+
}
171+
172+
/**
173+
* Get seconds (with leading zeros)
174+
*
175+
* @return string
176+
*/
177+
public function seconds(): string
178+
{
179+
return $this->raw->format('s');
180+
}
181+
182+
/**
183+
* Check if year is leap year
184+
*
185+
* @return bool
186+
*/
187+
public function isLeapYear(): bool
188+
{
189+
return (bool)$this->raw->format('L');
190+
}
191+
192+
/**
193+
* Get ISO 8601 week number of year
194+
*
195+
* @return int
196+
*/
197+
public function weekNumber(): int
198+
{
199+
return (int)$this->raw->format('W');
200+
}
201+
202+
/**
203+
* Get ISO 8601 formatted date (e.g., 2025-03-20T14:30:00+01:00)
204+
*
205+
* @return string
206+
*/
207+
public function iso(): string
208+
{
209+
return $this->raw->format(DateTimeInterface::ATOM);
210+
}
211+
212+
/**
213+
* Get RFC 2822 formatted date (e.g., Thu, 20 Mar 2025 14:30:00 +0100)
214+
*
215+
* @return string
216+
*/
217+
public function rfc(): string
218+
{
219+
return $this->raw->format(DateTime::RFC2822);
220+
}
221+
222+
/**
223+
* Get AM/PM format of time (e.g., 02:30 PM)
224+
*
225+
* @return string
226+
*/
227+
public function time12Hour(): string
228+
{
229+
return $this->raw->format('h:i A');
230+
}
231+
232+
/**
233+
* Get difference in days from today (negative if in past, positive if future)
234+
*
235+
* @return int
236+
* @throws \DateMalformedStringException
237+
*/
238+
public function diffInDays(): int
239+
{
240+
$today = new DateTimeImmutable('today', $this->raw->getTimezone());
241+
return (int)$today->diff($this->raw)->format('%r%a');
242+
}
243+
244+
/**
245+
* Check if the date is today
246+
*
247+
* @return bool
248+
*/
249+
public function isToday(): bool
250+
{
251+
return $this->raw->format('Y-m-d') === (new DateTimeImmutable('today', $this->raw->getTimezone()))->format('Y-m-d');
252+
}
253+
254+
/**
255+
* Set the timezone
256+
*
257+
* @param DateTimeZone|string $timezone
258+
* @return $this
259+
* @throws Exception
260+
*/
261+
public function setTimezone(DateTimeZone|string $timezone): self
262+
{
263+
if (!$timezone instanceof DateTimeZone) {
264+
$timezone = new DateTimeZone($timezone);
265+
}
266+
267+
$this->raw = $this->raw->setTimezone($timezone);
268+
269+
return $this;
270+
}
271+
272+
273+
/**
274+
* Get timezone identifier (e.g., Europe/Stockholm)
275+
*
276+
* @return string
277+
*/
278+
public function timezone(): string
279+
{
280+
return $this->raw->getTimezone()->getName();
281+
}
282+
283+
/**
284+
* Get hour and minutes
285+
*
286+
* @return string
287+
*/
288+
public function timestamp(): string
289+
{
290+
return $this->raw->getTimestamp();
291+
}
292+
293+
/**
294+
* Get year
295+
*
296+
* @param bool $shorthand
297+
* @return string
298+
*/
299+
public function year(bool $shorthand = false): string
300+
{
301+
return $this->raw->format($shorthand ? 'y' : 'Y');
302+
}
303+
304+
/**
305+
* Get month
306+
*
307+
* @return string
308+
*/
309+
public function month(): string
310+
{
311+
return $this->raw->format("m");
312+
}
313+
314+
/**
315+
* Get full name of month (e.g., January)
316+
*
317+
* @return string
318+
*/
319+
public function monthName(): string
320+
{
321+
return $this->raw->format('F');
322+
}
323+
324+
/**
325+
* Get shorthand name of month (e.g., Jan)
326+
*
327+
* @return string
328+
*/
329+
public function shortMonthName(): string
330+
{
331+
return $this->raw->format('M');
332+
}
333+
334+
335+
/**
336+
* Get month
337+
*
338+
* @return string
339+
*/
340+
public function day(): string
341+
{
342+
return $this->raw->format("d");
343+
}
344+
345+
/**
346+
* Get day of the week (numeric, 1 for Monday through 7 for Sunday)
347+
*
348+
* @return int
349+
*/
350+
public function dayOfWeek(): int
351+
{
352+
return (int)$this->raw->format('N');
353+
}
354+
355+
/**
356+
* Get full name of the weekday (e.g., Monday)
357+
*
358+
* @return string
359+
*/
360+
public function weekday(): string
361+
{
362+
return $this->raw->format('l');
363+
}
364+
365+
/**
366+
* Get short name of weekday (e.g., Mon)
367+
*
368+
* @return string
369+
*/
370+
public function shortWeekday(): string
371+
{
372+
return $this->raw->format('D');
373+
}
374+
375+
140376
/**
141377
* Get Value
142378
* @return string
@@ -149,11 +385,11 @@ public function __toString(): string
149385
/**
150386
* Return translation find array
151387
*
152-
* @param \DateTime $date
388+
* @param DateTime $date
153389
* @param string $locale
154390
* @return array
155391
*/
156-
protected function getTranslationData(\DateTime $date, string $locale): array
392+
protected function getTranslationData(DateTime $date, string $locale): array
157393
{
158394

159395
if($locale !== "en") {

0 commit comments

Comments
 (0)