16
16
use WizDevelop \PhpValueObject \ValueObjectMeta ;
17
17
18
18
/**
19
+ * @phpstan-type Year int<LocalDate::MIN_YEAR, LocalDate::MAX_YEAR>
20
+ * @phpstan-type Month int<1, 12>
21
+ * @phpstan-type Day int<1, 31>
22
+ *
19
23
* ローカル日付を表す値オブジェクト
20
24
*/
21
25
#[ValueObjectMeta(name: 'ローカル日付 ' )]
43
47
44
48
/**
45
49
* Avoid new() operator.
46
- * @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
47
- * @param int<1, 12> $month the month, from 1 to 12
48
- * @param int<1, 31> $day the day, from 1 to 31
50
+ * @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
51
+ * @param Month $month the month, from 1 to 12
52
+ * @param Day $day the day, from 1 to 31
49
53
*/
50
54
final private function __construct (
51
55
private int $ year ,
@@ -85,9 +89,9 @@ final public function jsonSerialize(): string
85
89
// MARK: factory methods
86
90
// -------------------------------------------------------------------------
87
91
/**
88
- * @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
89
- * @param int<1, 12> $month the month, from 1 to 12
90
- * @param int<1, 31> $day the day, from 1 to 31
92
+ * @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
93
+ * @param Month $month the month, from 1 to 12
94
+ * @param Day $day the day, from 1 to 31
91
95
*/
92
96
final public static function of (int $ year , int $ month , int $ day ): static
93
97
{
@@ -146,7 +150,7 @@ final public static function tryFromNullable(?DateTimeInterface $value): Result
146
150
return static ::tryFrom ($ value )->map (static fn ($ result ) => Option \some ($ result ));
147
151
}
148
152
149
- final public static function now (DateTimeZone $ timeZone ): static
153
+ final public static function now (DateTimeZone $ timeZone = new DateTimeZone ( ' Asia/Tokyo ' ) ): static
150
154
{
151
155
$ value = new DateTimeImmutable ('now ' , $ timeZone );
152
156
@@ -155,6 +159,11 @@ final public static function now(DateTimeZone $timeZone): static
155
159
return static ::of ($ year , $ month , $ day );
156
160
}
157
161
162
+ final public static function max (): static
163
+ {
164
+ return static ::of (self ::MAX_YEAR , 12 , 31 );
165
+ }
166
+
158
167
/**
159
168
* Obtains an instance of `LocalDate` from the epoch day count.
160
169
*
@@ -186,10 +195,10 @@ final public static function ofEpochDay(int $epochDay): static
186
195
// Convert march-based values back to January-based.
187
196
$ marchMonth0 = intdiv ($ marchDoy0 * 5 + 2 , 153 );
188
197
189
- /** @var int<1, 12> $month */
198
+ /** @var Month $month */
190
199
$ month = ($ marchMonth0 + 2 ) % 12 + 1 ;
191
200
192
- /** @var int<1, 31> $dom */
201
+ /** @var Day $dom */
193
202
$ dom = $ marchDoy0 - intdiv ($ marchMonth0 * 306 + 5 , 10 ) + 1 ;
194
203
195
204
$ yearEst += intdiv ($ marchMonth0 , 10 );
@@ -260,16 +269,14 @@ className: static::class,
260
269
);
261
270
}
262
271
263
-
264
-
265
272
return Result \ok (true );
266
273
}
267
274
268
275
/**
269
276
* 有効な日かどうかを判定
270
277
* @param int $year 年
271
- * @param int<1, 12> $monthOfYear 月
272
- * @param int<1, 31> $dayOfMonth 日
278
+ * @param Month $monthOfYear 月
279
+ * @param Day $dayOfMonth 日
273
280
* @return Result<bool,ValueObjectError>
274
281
*/
275
282
final protected static function isValidDate (int $ year , int $ monthOfYear , int $ dayOfMonth ): Result
@@ -337,7 +344,7 @@ final public function toISOString(): string
337
344
}
338
345
339
346
/**
340
- * @return int<self::MIN_YEAR, self::MAX_YEAR>
347
+ * @return Year
341
348
*/
342
349
final public function getYear (): int
343
350
{
@@ -346,15 +353,15 @@ final public function getYear(): int
346
353
}
347
354
348
355
/**
349
- * @return int<1, 12>
356
+ * @return Month
350
357
*/
351
358
final public function getMonth (): int
352
359
{
353
360
return $ this ->month ;
354
361
}
355
362
356
363
/**
357
- * @return int<1, 31>
364
+ * @return Day
358
365
*/
359
366
final public function getDay (): int
360
367
{
@@ -409,6 +416,11 @@ final public function compareTo(self $that): int
409
416
return 0 ;
410
417
}
411
418
419
+ final public function is (self $ that ): bool
420
+ {
421
+ return $ this ->compareTo ($ that ) === 0 ;
422
+ }
423
+
412
424
final public function isBefore (self $ that ): bool
413
425
{
414
426
return $ this ->compareTo ($ that ) === -1 ;
@@ -463,7 +475,7 @@ final public function addMonths(int $months): static
463
475
464
476
$ yearDiff = Math::floorDiv ($ month , 12 );
465
477
466
- /** @var int<1, 12> $month */
478
+ /** @var Month $month */
467
479
$ month = Math::floorMod ($ month , 12 ) + 1 ;
468
480
469
481
$ year = $ this ->year + $ yearDiff ;
@@ -591,17 +603,17 @@ final public function toEpochDay(): int
591
603
// MARK: private methods
592
604
// -------------------------------------------------------------------------
593
605
/**
594
- * @return array{0:int<self::MIN_YEAR, self::MAX_YEAR>, 1:int<1, 12>, 2:int<1, 31> }
606
+ * @return array{0:Year, 1:Month, 2:Day }
595
607
*/
596
608
private static function extractDate (DateTimeInterface $ value ): array
597
609
{
598
- /** @var int<self::MIN_YEAR, self::MAX_YEAR> */
610
+ /** @var Year */
599
611
$ year = (int )$ value ->format ('Y ' );
600
612
601
- /** @var int<1, 12> */
613
+ /** @var Month */
602
614
$ month = (int )$ value ->format ('n ' );
603
615
604
- /** @var int<1, 31> */
616
+ /** @var Day */
605
617
$ day = (int )$ value ->format ('j ' );
606
618
607
619
return [$ year , $ month , $ day ];
@@ -610,9 +622,9 @@ private static function extractDate(DateTimeInterface $value): array
610
622
/**
611
623
* Resolves the date, resolving days past the end of month.
612
624
*
613
- * @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
614
- * @param int<1, 12> $month the month-of-year to represent
615
- * @param int<1, 31> $day the day-of-month to represent, validated from 1 to 31
625
+ * @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
626
+ * @param Month $month the month-of-year to represent
627
+ * @param Day $day the day-of-month to represent, validated from 1 to 31
616
628
*/
617
629
private static function resolvePreviousValid (int $ year , int $ month , int $ day ): static
618
630
{
@@ -632,7 +644,7 @@ private static function isLeapYear(int $year): bool
632
644
}
633
645
634
646
/**
635
- * @param int<1, 12> $month
647
+ * @param Month $month
636
648
* @return int<28, 31>
637
649
*/
638
650
private static function lengthOfMonth (int $ year , int $ month ): int
@@ -646,8 +658,8 @@ private static function lengthOfMonth(int $year, int $month): int
646
658
647
659
/**
648
660
* Returns whether this date is the last day of the month.
649
- * @param int<1, 12> $month
650
- * @param int<1, 31> $day
661
+ * @param Month $month
662
+ * @param Day $day
651
663
*/
652
664
private static function isEndOfMonth (int $ year , int $ month , int $ day ): bool
653
665
{
0 commit comments