Skip to content

Commit a09c561

Browse files
committed
LocalDateRange の属性 from, to の型を継承時に指定できるようにする
Fixes #32
1 parent edcaa11 commit a09c561

File tree

5 files changed

+416
-236
lines changed

5 files changed

+416
-236
lines changed

src/DateTime/LocalDate.php

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
use WizDevelop\PhpValueObject\ValueObjectMeta;
1717

1818
/**
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+
*
1923
* ローカル日付を表す値オブジェクト
2024
*/
2125
#[ValueObjectMeta(name: 'ローカル日付')]
@@ -43,9 +47,9 @@
4347

4448
/**
4549
* 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
4953
*/
5054
final private function __construct(
5155
private int $year,
@@ -85,9 +89,9 @@ final public function jsonSerialize(): string
8589
// MARK: factory methods
8690
// -------------------------------------------------------------------------
8791
/**
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
9195
*/
9296
final public static function of(int $year, int $month, int $day): static
9397
{
@@ -191,10 +195,10 @@ final public static function ofEpochDay(int $epochDay): static
191195
// Convert march-based values back to January-based.
192196
$marchMonth0 = intdiv($marchDoy0 * 5 + 2, 153);
193197

194-
/** @var int<1, 12> $month */
198+
/** @var Month $month */
195199
$month = ($marchMonth0 + 2) % 12 + 1;
196200

197-
/** @var int<1, 31> $dom */
201+
/** @var Day $dom */
198202
$dom = $marchDoy0 - intdiv($marchMonth0 * 306 + 5, 10) + 1;
199203

200204
$yearEst += intdiv($marchMonth0, 10);
@@ -271,8 +275,8 @@ className: static::class,
271275
/**
272276
* 有効な日かどうかを判定
273277
* @param int $year 年
274-
* @param int<1, 12> $monthOfYear 月
275-
* @param int<1, 31> $dayOfMonth 日
278+
* @param Month $monthOfYear 月
279+
* @param Day $dayOfMonth 日
276280
* @return Result<bool,ValueObjectError>
277281
*/
278282
final protected static function isValidDate(int $year, int $monthOfYear, int $dayOfMonth): Result
@@ -340,7 +344,7 @@ final public function toISOString(): string
340344
}
341345

342346
/**
343-
* @return int<self::MIN_YEAR, self::MAX_YEAR>
347+
* @return Year
344348
*/
345349
final public function getYear(): int
346350
{
@@ -349,15 +353,15 @@ final public function getYear(): int
349353
}
350354

351355
/**
352-
* @return int<1, 12>
356+
* @return Month
353357
*/
354358
final public function getMonth(): int
355359
{
356360
return $this->month;
357361
}
358362

359363
/**
360-
* @return int<1, 31>
364+
* @return Day
361365
*/
362366
final public function getDay(): int
363367
{
@@ -471,7 +475,7 @@ final public function addMonths(int $months): static
471475

472476
$yearDiff = Math::floorDiv($month, 12);
473477

474-
/** @var int<1, 12> $month */
478+
/** @var Month $month */
475479
$month = Math::floorMod($month, 12) + 1;
476480

477481
$year = $this->year + $yearDiff;
@@ -599,17 +603,17 @@ final public function toEpochDay(): int
599603
// MARK: private methods
600604
// -------------------------------------------------------------------------
601605
/**
602-
* @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}
603607
*/
604608
private static function extractDate(DateTimeInterface $value): array
605609
{
606-
/** @var int<self::MIN_YEAR, self::MAX_YEAR> */
610+
/** @var Year */
607611
$year = (int)$value->format('Y');
608612

609-
/** @var int<1, 12> */
613+
/** @var Month */
610614
$month = (int)$value->format('n');
611615

612-
/** @var int<1, 31> */
616+
/** @var Day */
613617
$day = (int)$value->format('j');
614618

615619
return [$year, $month, $day];
@@ -618,9 +622,9 @@ private static function extractDate(DateTimeInterface $value): array
618622
/**
619623
* Resolves the date, resolving days past the end of month.
620624
*
621-
* @param int $year the year to represent, validated from MIN_YEAR to MAX_YEAR
622-
* @param int<1, 12> $month the month-of-year to represent
623-
* @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
624628
*/
625629
private static function resolvePreviousValid(int $year, int $month, int $day): static
626630
{
@@ -640,7 +644,7 @@ private static function isLeapYear(int $year): bool
640644
}
641645

642646
/**
643-
* @param int<1, 12> $month
647+
* @param Month $month
644648
* @return int<28, 31>
645649
*/
646650
private static function lengthOfMonth(int $year, int $month): int
@@ -654,8 +658,8 @@ private static function lengthOfMonth(int $year, int $month): int
654658

655659
/**
656660
* Returns whether this date is the last day of the month.
657-
* @param int<1, 12> $month
658-
* @param int<1, 31> $day
661+
* @param Month $month
662+
* @param Day $day
659663
*/
660664
private static function isEndOfMonth(int $year, int $month, int $day): bool
661665
{

src/DateTime/LocalDateRange.php

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -242,26 +242,6 @@ final public function strictlyBefore(self $other): bool
242242
);
243243
}
244244

245-
/**
246-
* 境界での重なりを考慮した判定
247-
*
248-
* @param self<TStart,TEnd> $other
249-
*/
250-
private function hasOverlapAt(self $other): bool
251-
{
252-
// 開始点での重なり判定
253-
$startOverlap = $this->contains($other->from) || $other->contains($this->from);
254-
255-
// 終了点での重なり判定
256-
$endOverlap = $this->contains($other->to) || $other->contains($this->to);
257-
258-
// 一方が他方を完全に含む場合
259-
$containment = ($this->from->isBeforeOrEqualTo($other->from) && $this->to->isAfterOrEqualTo($other->to))
260-
|| ($other->from->isBeforeOrEqualTo($this->from) && $other->to->isAfterOrEqualTo($this->to));
261-
262-
return $startOverlap || $endOverlap || $containment;
263-
}
264-
265245
/**
266246
* 範囲の日数を返す
267247
* 注意: 開区間の場合、実際の日数は計算結果より1日または2日少なくなる可能性があります

src/DateTime/LocalDateTime.php

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
use WizDevelop\PhpValueObject\ValueObjectMeta;
1717

1818
/**
19+
* @phpstan-import-type Hour from LocalTime
20+
* @phpstan-import-type Minute from LocalTime
21+
* @phpstan-import-type Second from LocalTime
22+
* @phpstan-import-type Micro from LocalTime
23+
*
24+
* @phpstan-import-type Year from LocalDate
25+
* @phpstan-import-type Month from LocalDate
26+
* @phpstan-import-type Day from LocalDate
27+
*
1928
* ローカル日時を表す値オブジェクト
2029
*/
2130
#[ValueObjectMeta(name: 'ローカル日時')]
@@ -161,55 +170,55 @@ final public function getTime(): LocalTime
161170
}
162171

163172
/**
164-
* @return int<-9999, 9999>
173+
* @return Year
165174
*/
166175
final public function getYear(): int
167176
{
168177
return $this->date->getYear();
169178
}
170179

171180
/**
172-
* @return int<1, 12>
181+
* @return Month
173182
*/
174183
final public function getMonth(): int
175184
{
176185
return $this->date->getMonth();
177186
}
178187

179188
/**
180-
* @return int<1, 31>
189+
* @return Day
181190
*/
182191
final public function getDay(): int
183192
{
184193
return $this->date->getDay();
185194
}
186195

187196
/**
188-
* @return int<0, 23>
197+
* @return Hour
189198
*/
190199
final public function getHour(): int
191200
{
192201
return $this->time->getHour();
193202
}
194203

195204
/**
196-
* @return int<0, 59>
205+
* @return Minute
197206
*/
198207
final public function getMinute(): int
199208
{
200209
return $this->time->getMinute();
201210
}
202211

203212
/**
204-
* @return int<0, 59>
213+
* @return Second
205214
*/
206215
final public function getSecond(): int
207216
{
208217
return $this->time->getSecond();
209218
}
210219

211220
/**
212-
* @return int<0, 999999>
221+
* @return Micro
213222
*/
214223
final public function getMicro(): int
215224
{
@@ -517,7 +526,7 @@ private function addWithOverflow(int $hours, int $minutes, int $seconds, int $mi
517526
$totMicros = $micros * $sign + $this->time->getMicro();
518527
$totSeconds += Math::floorDiv($totMicros, LocalTime::MICROS_PER_SECOND);
519528

520-
/** @var int<0, 999999> */
529+
/** @var Micro */
521530
$newMicro = Math::floorMod($totMicros, LocalTime::MICROS_PER_SECOND);
522531

523532
$totDays += Math::floorDiv($totSeconds, LocalTime::SECONDS_PER_DAY);

0 commit comments

Comments
 (0)