diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c5295b..1a7287c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,3 +27,10 @@ 3. 新增:每日宜忌、时辰宜忌。 4. 新增:支持方法扩展。 5. 修复:农历日获取时辰列表遇闰月报错的问题。 + +## [1.1.1] - 2024-07-30 +1. 新增:时辰获取黄道黑道十二神。 +2. 新增:五行和方位互转。 +3. 新增:天干五合、地支六合、地支六害。 +4. 修复:获取当年第几周报错的问题。 +5. 优化:性能。 diff --git a/src/culture/Direction.php b/src/culture/Direction.php index 3432151..cb4edc7 100644 --- a/src/culture/Direction.php +++ b/src/culture/Direction.php @@ -50,4 +50,14 @@ function getLand(): Land { return Land::fromIndex($this->index); } + + /** + * 五行 + * + * @return Element 五行 + */ + function getElement(): Element + { + return Element::fromIndex([4, 2, 0, 0, 2, 3, 3, 2, 1][$this->index]); + } } diff --git a/src/culture/Element.php b/src/culture/Element.php index 761ef05..c1e82b6 100644 --- a/src/culture/Element.php +++ b/src/culture/Element.php @@ -77,4 +77,13 @@ function getRestrained(): static { return $this->next(-2); } + + /** + * 方位 + * @return Direction 方位 + */ + function getDirection(): Direction + { + return Direction::fromIndex([2, 8, 4, 6, 0][$this->index]); + } } diff --git a/src/holiday/LegalHoliday.php b/src/holiday/LegalHoliday.php index b398f39..ceefbb3 100644 --- a/src/holiday/LegalHoliday.php +++ b/src/holiday/LegalHoliday.php @@ -72,21 +72,28 @@ function next(int $n): ?static } $index += $n; $y = $year; - $forward = $n > 0; - $add = $forward ? 1 : -1; - while ($forward ? ($index >= $size) : ($index < 0)) { - if ($forward) { + if ($n > 0) { + while ($index >= $size) { $index -= $size; + $y += 1; + $size = 0; + if(preg_match_all(sprintf($reg, $y), static::$DATA, $matches)) { + $size = count($matches[0]); + } + if ($size < 1) { + return null; + } } - $y += $add; - $size = 0; - if(preg_match_all(sprintf($reg, $y), static::$DATA, $matches)) { - $size = count($matches[0]); - } - if ($size < 1) { - return null; - } - if (!$forward) { + } else { + while ($index < 0) { + $y -= 1; + $size = 0; + if(preg_match_all(sprintf($reg, $y), static::$DATA, $matches)) { + $size = count($matches[0]); + } + if ($size < 1) { + return null; + } $index += $size; } } diff --git a/src/lunar/LunarDay.php b/src/lunar/LunarDay.php index 802d9e7..d977750 100644 --- a/src/lunar/LunarDay.php +++ b/src/lunar/LunarDay.php @@ -6,6 +6,7 @@ use com\tyme\AbstractTyme; use com\tyme\culture\Direction; use com\tyme\culture\Duty; +use com\tyme\culture\Element; use com\tyme\culture\fetus\FetusDay; use com\tyme\culture\God; use com\tyme\culture\Phase; @@ -109,25 +110,7 @@ function __toString(): string function next(int $n): LunarDay { - if ($n == 0) { - return self::fromYmd($this->getYear(), $this->getMonth(), $this->day); - } - $d = $this->day + $n; - $m = $this->month; - $dayCount = $m->getDayCount(); - $forward = $n > 0; - $add = $forward ? 1 : -1; - while ($forward ? ($d > $dayCount) : ($d <= 0)) { - if ($forward) { - $d -= $dayCount; - } - $m = $m->next($add); - $dayCount = $m->getDayCount(); - if (!$forward) { - $d += $dayCount; - } - } - return self::fromYmd($m->getYear(), $m->getMonthWithLeap(), $d); + return $n == 0 ? self::fromYmd($this->getYear(), $this->getMonth(), $this->day) : $this->getSolarDay()->next($n)->getLunarDay(); } /** @@ -296,10 +279,7 @@ function getNineStar(): NineStar function getJupiterDirection(): Direction { $index = $this->getSixtyCycle()->getIndex(); - if ($index % 12 < 6) { - return Direction::fromIndex([2, 8, 4, 6, 0][intdiv($index, 12)]); - } - return $this->month->getLunarYear()->getJupiterDirection(); + return $index % 12 < 6 ? Element::fromIndex(intdiv($index, 12))->getDirection() : $this->month->getLunarYear()->getJupiterDirection(); } /** @@ -403,13 +383,4 @@ function getSixStar(): SixStar { return SixStar::fromIndex(($this->month->getMonth() + $this->day - 2) % 6); } - - function equals(mixed $o): bool - { - if (!($o instanceof LunarDay)) { - return false; - } - return $this->month->equals($o->getMonth()) && $this->day == $o->getDay(); - } - } diff --git a/src/lunar/LunarHour.php b/src/lunar/LunarHour.php index d19520e..69c20bb 100644 --- a/src/lunar/LunarHour.php +++ b/src/lunar/LunarHour.php @@ -5,6 +5,7 @@ use com\tyme\AbstractTyme; use com\tyme\culture\star\nine\NineStar; +use com\tyme\culture\star\twelve\TwelveStar; use com\tyme\culture\Taboo; use com\tyme\eightchar\EightChar; use com\tyme\sixtycycle\EarthBranch; @@ -262,6 +263,16 @@ function getSixtyCycle(): SixtyCycle return SixtyCycle::fromName(sprintf('%s%s', HeavenStem::fromIndex($heavenStemIndex)->getName(), EarthBranch::fromIndex($earthBranchIndex)->getName())); } + /** + * 黄道黑道十二神 + * + * @return TwelveStar 黄道黑道十二神 + */ + function getTwelveStar(): TwelveStar + { + return TwelveStar::fromIndex($this->getSixtyCycle()->getEarthBranch()->getIndex() + (8 - $this->getDaySixtyCycle()->getEarthBranch()->getIndex() % 6) * 2); + } + /** * 九星(时家紫白星歌诀:三元时白最为佳,冬至阳生顺莫差,孟日七宫仲一白,季日四绿发萌芽,每把时辰起甲子,本时星耀照光华,时星移入中宫去,顺飞八方逐细查。夏至阴生逆回首,孟归三碧季加六,仲在九宫时起甲,依然掌中逆轮跨。) * @@ -319,12 +330,4 @@ function getAvoids(): array { return Taboo::getHourAvoids($this->getDaySixtyCycle(), $this->getSixtyCycle()); } - - function equals(mixed $o): bool - { - if (!($o instanceof LunarHour)) { - return false; - } - return $this->day->equals($o->getDay()) && $this->hour == $o->getHour() && $this->minute == $o->getMinute() && $this->second == $o->getSecond(); - } } diff --git a/src/lunar/LunarMonth.php b/src/lunar/LunarMonth.php index 4f9937b..01a667f 100644 --- a/src/lunar/LunarMonth.php +++ b/src/lunar/LunarMonth.php @@ -22,6 +22,11 @@ */ class LunarMonth extends AbstractTyme { + /** + * @var array 缓存 + */ + private static array $cache = array(); + static array $NAMES = ['正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']; @@ -55,58 +60,85 @@ class LunarMonth extends AbstractTyme */ protected JulianDay $firstJulianDay; - protected function __construct(int $year, int $month) + protected function __construct(int $year, int $month, array $cache = null) { - $currentYear = LunarYear::fromYear($year); - $currentLeapMonth = $currentYear->getLeapMonth(); - if ($month == 0 || $month > 12 || $month < -12) { - throw new InvalidArgumentException(sprintf('illegal lunar month: %d', $month)); - } - $leap = $month < 0; - $m = abs($month); - if ($leap && $m != $currentLeapMonth) { - throw new InvalidArgumentException(sprintf('illegal leap month %d in lunar year %d', $m, $year)); - } + if ($cache !== null) { + $m = (int)$cache[1]; + $this->year = LunarYear::fromYear((int)$cache[0]); + $this->month = abs($m); + $this->leap = $m < 0; + $this->dayCount = (int)$cache[2]; + $this->indexInYear = (int)$cache[3]; + $this->firstJulianDay = JulianDay::fromJulianDay((double)$cache[4]); + } else { + $currentYear = LunarYear::fromYear($year); + $currentLeapMonth = $currentYear->getLeapMonth(); + if ($month == 0 || $month > 12 || $month < -12) { + throw new InvalidArgumentException(sprintf('illegal lunar month: %d', $month)); + } + $leap = $month < 0; + $m = abs($month); + if ($leap && $m != $currentLeapMonth) { + throw new InvalidArgumentException(sprintf('illegal leap month %d in lunar year %d', $m, $year)); + } - // 冬至 - $dongZhi = SolarTerm::fromIndex($year, 0); - $dongZhiJd = $dongZhi->getCursoryJulianDay(); + // 冬至 + $dongZhi = SolarTerm::fromIndex($year, 0); + $dongZhiJd = $dongZhi->getCursoryJulianDay(); - // 冬至前的初一,今年首朔的日月黄经差 - $w = ShouXingUtil::calcShuo($dongZhiJd); - if ($w > $dongZhiJd) { - $w -= 29.53; - } + // 冬至前的初一,今年首朔的日月黄经差 + $w = ShouXingUtil::calcShuo($dongZhiJd); + if ($w > $dongZhiJd) { + $w -= 29.53; + } - // 正常情况正月初一为第3个朔日,但有些特殊的 - $offset = 2; - if ($year > 8 && $year < 24) { - $offset = 1; - } else if (LunarYear::fromYear($year - 1)->getLeapMonth() > 10 && $year != 239 && $year != 240) { - $offset = 3; - } + // 正常情况正月初一为第3个朔日,但有些特殊的 + $offset = 2; + if ($year > 8 && $year < 24) { + $offset = 1; + } else if (LunarYear::fromYear($year - 1)->getLeapMonth() > 10 && $year != 239 && $year != 240) { + $offset = 3; + } - // 位于当年的索引 - $index = $m - 1; - if ($leap || ($currentLeapMonth > 0 && $m > $currentLeapMonth)) { - $index += 1; + // 位于当年的索引 + $index = $m - 1; + if ($leap || ($currentLeapMonth > 0 && $m > $currentLeapMonth)) { + $index += 1; + } + $this->indexInYear = $index; + + // 本月初一 + $w += 29.5306 * ($offset + $index); + $firstDay = ShouXingUtil::calcShuo($w); + $this->firstJulianDay = JulianDay::fromJulianDay(JulianDay::J2000 + $firstDay); + // 本月天数 = 下月初一 - 本月初一 + $this->dayCount = (int)(ShouXingUtil::calcShuo($w + 29.5306) - $firstDay); + $this->year = $currentYear; + $this->month = $m; + $this->leap = $leap; } - $this->indexInYear = $index; - - // 本月初一 - $w += 29.5306 * ($offset + $index); - $firstDay = ShouXingUtil::calcShuo($w); - $this->firstJulianDay = JulianDay::fromJulianDay(JulianDay::J2000 + $firstDay); - // 本月天数 = 下月初一 - 本月初一 - $this->dayCount = (int)(ShouXingUtil::calcShuo($w + 29.5306) - $firstDay); - $this->year = $currentYear; - $this->month = $m; - $this->leap = $leap; } static function fromYm(int $year, int $month): static { - return new static($year, $month); + $c = null; + $key = sprintf("%d%d", $year, $month); + if (!empty(static::$cache[$key])) { + $c = static::$cache[$key]; + } + if (null != $c) { + $m = new static(0, 0, $c); + } else { + $m = new static($year, $month); + static::$cache[$key] = [ + $m->getYear(), + $m->getMonthWithLeap(), + $m->getDayCount(), + $m->getIndexInYear(), + $m->getFirstJulianDay()->getDay() + ]; + } + return $m; } /** @@ -233,18 +265,19 @@ function next(int $n): LunarMonth $m = $this->indexInYear + 1 + $n; $y = $this->year; $leapMonth = $y->getLeapMonth(); - $monthSize = 12 + ($leapMonth > 0 ? 1 : 0); - $forward = $n > 0; - $add = $forward ? 1 : -1; - while ($forward ? ($m > $monthSize) : ($m <= 0)) { - if ($forward) { - $m -= $monthSize; + if ($n > 0) { + $monthCount = $leapMonth > 0 ? 13 : 12; + while ($m > $monthCount) { + $m -= $monthCount; + $y = $y->next(1); + $leapMonth = $y->getLeapMonth(); + $monthCount = $leapMonth > 0 ? 13 : 12; } - $y = $y->next($add); - $leapMonth = $y->getLeapMonth(); - $monthSize = 12 + ($leapMonth > 0 ? 1 : 0); - if (!$forward) { - $m += $monthSize; + } else { + while ($m <= 0) { + $y = $y->next(-1); + $leapMonth = $y->getLeapMonth(); + $m += $leapMonth > 0 ? 13 : 12; } } $leap = false; @@ -335,13 +368,4 @@ function getFetus(): FetusMonth { return FetusMonth::fromLunarMonth($this); } - - function equals(mixed $o): bool - { - if (!($o instanceof LunarMonth)) { - return false; - } - return $this->getYear() == $o->getYear() && $this->getMonthWithLeap() == $o->getMonthWithLeap(); - } - } diff --git a/src/lunar/LunarWeek.php b/src/lunar/LunarWeek.php index 707a516..f90da1c 100644 --- a/src/lunar/LunarWeek.php +++ b/src/lunar/LunarWeek.php @@ -115,32 +115,29 @@ function __toString(): string function next(int $n): static { + $startIndex = $this->start->getIndex(); if ($n == 0) { - return static::fromYm($this->getYear(), $this->getMonth(), $this->index, $this->start->getIndex()); + return static::fromYm($this->getYear(), $this->getMonth(), $this->index, $startIndex); } $d = $this->index + $n; $m = $this->month; - $startIndex = $this->start->getIndex(); - $weekCount = $m->getWeekCount($startIndex); - $forward = $n > 0; - $add = $forward ? 1 : -1; - while ($forward ? ($d >= $weekCount) : ($d < 0)) { - if ($forward) { + if ($n > 0) { + $weekCount = $m->getWeekCount($startIndex); + while ($d >= $weekCount) { $d -= $weekCount; - } else { + $m = $m->next(1); if (!LunarDay::fromYmd($m->getYear(), $m->getMonthWithLeap(), 1)->getWeek()->equals($this->start)) { - $d += $add; + $d += 1; } + $weekCount = $m->getWeekCount($startIndex); } - $m = $m->next($add); - if ($forward) { + } else { + while ($d < 0) { if (!LunarDay::fromYmd($m->getYear(), $m->getMonthWithLeap(), 1)->getWeek()->equals($this->start)) { - $d += $add; + $d -= 1; } - } - $weekCount = $m->getWeekCount($startIndex); - if (!$forward) { - $d += $weekCount; + $m = $m->next(-1); + $d += $m->getWeekCount($startIndex); } } return static::fromYm($m->getYear(), $m->getMonthWithLeap(), $d, $startIndex); @@ -173,4 +170,12 @@ function getDays(): array return $l; } + /** + * @param mixed $o 对象 + * @return bool true/false + */ + function equals(mixed $o): bool + { + return $o instanceof LunarWeek && $this->getFirstDay() . $this->equals($o->getFirstDay()); + } } diff --git a/src/lunar/LunarYear.php b/src/lunar/LunarYear.php index b7cda5d..f1a9cc0 100644 --- a/src/lunar/LunarYear.php +++ b/src/lunar/LunarYear.php @@ -94,6 +94,16 @@ function getDayCount(): int return $n; } + /** + * 月数 + * + * @return int 月数 + */ + function getMonthCount(): int + { + return $this->getLeapMonth() > 0 ? 13 : 12; + } + /** * 依据国家标准《农历的编算和颁行》GB/T 33661-2017,农历年有2种命名方法:干支纪年法和生肖纪年法,这里默认采用干支纪年法。 * @@ -176,16 +186,10 @@ function getMonths(): array { $l = array(); $m = LunarMonth::fromYm($this->year, 1); - while ($m->getYear()->getYear() == $this->year) { + while ($m->getYear() == $this->year) { $l[] = $m; $m = $m->next(1); } return $l; } - - function equals(mixed $o): bool - { - return $o instanceof LunarYear && $o->getYear() == $this->year; - } - } diff --git a/src/sixtycycle/EarthBranch.php b/src/sixtycycle/EarthBranch.php index 58aa714..631d501 100644 --- a/src/sixtycycle/EarthBranch.php +++ b/src/sixtycycle/EarthBranch.php @@ -116,7 +116,7 @@ function getDirection(): Direction } /** - * 相冲的地支(子午冲,丑未冲,寅申冲,辰戌冲,卯酉冲,巳亥冲) + * 六冲(子午冲,丑未冲,寅申冲,辰戌冲,卯酉冲,巳亥冲) * * @return EarthBranch 地支 */ @@ -125,6 +125,36 @@ function getOpposite(): static return $this->next(6); } + /** + * 六合(子丑合,寅亥合,卯戌合,辰酉合,巳申合,午未合) + * + * @return EarthBranch 地支 + */ + function getCombine(): static + { + return $this->fromIndex(1 - $this->index); + } + + /** + * 合化(子丑合化土,寅亥合化木,卯戌合化火,辰酉合化金,巳申合化水,午未合化土) + * @param EarthBranch $target 地支 + * @return Element|null 五行,如果无法合化,返回null + */ + function combine(EarthBranch $target): ?Element + { + return $this->getCombine()->equals($target) ? Element::fromIndex([2, 2, 0, 1, 3, 4, 2, 2, 4, 3, 1, 0][$this->index]) : null; + } + + /** + * 六害(子未害、丑午害、寅巳害、卯辰害、申亥害、酉戌害) + * + * @return EarthBranch 地支 + */ + function getHarm(): static + { + return $this->fromIndex(19 - $this->index); + } + /** * 煞(逢巳日、酉日、丑日必煞东;亥日、卯日、未日必煞西;申日、子日、辰日必煞南;寅日、午日、戌日必煞北。) * diff --git a/src/sixtycycle/HeavenStem.php b/src/sixtycycle/HeavenStem.php index 4784eb8..77afa42 100644 --- a/src/sixtycycle/HeavenStem.php +++ b/src/sixtycycle/HeavenStem.php @@ -95,7 +95,7 @@ function getTenStar(HeavenStem $target): TenStar */ function getDirection(): Direction { - return Direction::fromIndex([2, 8, 4, 6, 0][intdiv($this->index, 2)]); + return $this->getElement()->getDirection(); } /** @@ -169,4 +169,24 @@ function getTerrain(EarthBranch $earthBranch): Terrain $earthBranchIndex = $earthBranch->getIndex(); return Terrain::fromIndex([1, 6, 10, 9, 10, 9, 7, 0, 4, 3][$this->index] + (YinYang::YANG == $this->getYinYang() ? $earthBranchIndex : -$earthBranchIndex)); } + + /** + * 五合(甲己合,乙庚合,丙辛合,丁壬合,戊癸合) + * + * @return HeavenStem 天干 + */ + function getCombine(): static + { + return $this->next(5); + } + + /** + * 合化(甲己合化土,乙庚合化金,丙辛合化水,丁壬合化木,戊癸合化火) + * @param HeavenStem $target 天干 + * @return Element|null 五行,如果无法合化,返回null + */ + function combine(HeavenStem $target): ?Element + { + return $this->getCombine()->equals($target) ? Element::fromIndex($this->index + 2) : null; + } } diff --git a/src/solar/SolarDay.php b/src/solar/SolarDay.php index 81d83e2..24efc6e 100644 --- a/src/solar/SolarDay.php +++ b/src/solar/SolarDay.php @@ -402,7 +402,7 @@ function getLunarDay(): LunarDay $days = $this->subtract($m->getFirstJulianDay()->getSolarDay()); while ($days < 0) { $m = $m->next(-1); - $days = $this->subtract($m->getFirstJulianDay()->getSolarDay()); + $days += $m->getDayCount(); } return LunarDay::fromYmd($m->getYear(), $m->getMonthWithLeap(), $days + 1); } diff --git a/src/solar/SolarHalfYear.php b/src/solar/SolarHalfYear.php index 461e41a..b43b91a 100644 --- a/src/solar/SolarHalfYear.php +++ b/src/solar/SolarHalfYear.php @@ -101,8 +101,8 @@ function getMonths(): array { $l = array(); $y = $this->getYear(); - for ($i = 0; $i < 6; $i++) { - $l[] = SolarMonth::fromYm($y, $this->index * 6 + $i + 1); + for ($i = 1; $i < 7; $i++) { + $l[] = SolarMonth::fromYm($y, $this->index * 6 + $i); } return $l; } diff --git a/src/solar/SolarMonth.php b/src/solar/SolarMonth.php index 7373fbc..9045084 100644 --- a/src/solar/SolarMonth.php +++ b/src/solar/SolarMonth.php @@ -173,8 +173,8 @@ function getDays(): array $size = $this->getDayCount(); $y = $this->getYear(); $l = array(); - for ($i = 0; $i < $size; $i++) { - $l[] = SolarDay::fromYmd($y, $this->month, $i + 1); + for ($i = 1; $i <= $size; $i++) { + $l[] = SolarDay::fromYmd($y, $this->month, $i); } return $l; } diff --git a/src/solar/SolarSeason.php b/src/solar/SolarSeason.php index 8ac8544..608c42d 100644 --- a/src/solar/SolarSeason.php +++ b/src/solar/SolarSeason.php @@ -101,8 +101,8 @@ function getMonths(): array { $l = array(); $y = $this->getYear(); - for ($i = 0; $i < 3; $i++) { - $l[] = SolarMonth::fromYm($y, $this->index * 3 + $i + 1); + for ($i = 1; $i < 4; $i++) { + $l[] = SolarMonth::fromYm($y, $this->index * 3 + $i); } return $l; } diff --git a/src/solar/SolarWeek.php b/src/solar/SolarWeek.php index a71344e..0558aaf 100644 --- a/src/solar/SolarWeek.php +++ b/src/solar/SolarWeek.php @@ -101,9 +101,10 @@ function getIndex(): int function getIndexInYear(): int { $i = 0; + $firstDay = $this->getFirstDay(); // 今年第1周 $w = self::fromYm($this->getYear(), 1, 0, $this->start->getIndex()); - while (!$w->equals($this)) { + while (!$w->getFirstDay()->equals($firstDay)) { $w = $w->next(1); $i += 1; } @@ -132,32 +133,29 @@ function __toString(): string function next(int $n): static { + $startIndex = $this->start->getIndex(); if ($n == 0) { - return static::fromYm($this->getYear(), $this->getMonth(), $this->index, $this->start->getIndex()); + return static::fromYm($this->getYear(), $this->getMonth(), $this->index, $startIndex); } $d = $this->index + $n; $m = $this->month; - $startIndex = $this->start->getIndex(); - $weekCount = $m->getWeekCount($startIndex); - $forward = $n > 0; - $add = $forward ? 1 : -1; - while ($forward ? ($d >= $weekCount) : ($d < 0)) { - if ($forward) { + if ($n > 0) { + $weekCount = $m->getWeekCount($startIndex); + while ($d >= $weekCount) { $d -= $weekCount; - } else { + $m = $m->next(1); if (!SolarDay::fromYmd($m->getYear(), $m->getMonth(), 1)->getWeek()->equals($this->start)) { - $d += $add; + $d += 1; } + $weekCount = $m->getWeekCount($startIndex); } - $m = $m->next($add); - if ($forward) { + } else { + while ($d < 0) { if (!SolarDay::fromYmd($m->getYear(), $m->getMonth(), 1)->getWeek()->equals($this->start)) { - $d += $add; + $d -= 1; } - } - $weekCount = $m->getWeekCount($startIndex); - if (!$forward) { - $d += $weekCount; + $m = $m->next(-1); + $d += $m->getWeekCount($startIndex); } } return static::fromYm($m->getYear(), $m->getMonth(), $d, $startIndex); @@ -190,4 +188,12 @@ function getDays(): array return $l; } + /** + * @param mixed $o 对象 + * @return bool true/false + */ + function equals(mixed $o): bool + { + return $o instanceof SolarWeek && $this->getFirstDay().$this->equals($o->getFirstDay()); + } } diff --git a/src/solar/SolarYear.php b/src/solar/SolarYear.php index e2acdab..8a79be8 100644 --- a/src/solar/SolarYear.php +++ b/src/solar/SolarYear.php @@ -84,8 +84,8 @@ function next(int $n): static function getMonths(): array { $l = array(); - for ($i = 0; $i < 12; $i++) { - $l[] = SolarMonth::fromYm($this->year, $i + 1); + for ($i = 1; $i < 13; $i++) { + $l[] = SolarMonth::fromYm($this->year, $i); } return $l; }