From e3c108885319f8d9420e79c06c42236b31ae8cb9 Mon Sep 17 00:00:00 2001 From: xentixar Date: Sat, 6 Sep 2025 14:36:45 +0545 Subject: [PATCH 1/3] Add functions to check if a date is a weekend or weekday --- ext/date/lib/dow.c | 30 ++++++++++++++++++++ ext/date/lib/timelib.h | 6 ++++ ext/date/php_date.c | 56 +++++++++++++++++++++++++++++++++++++ ext/date/php_date.stub.php | 18 ++++++++++++ ext/date/php_date_arginfo.h | 23 +++++++++++++++ 5 files changed, 133 insertions(+) diff --git a/ext/date/lib/dow.c b/ext/date/lib/dow.c index c288e5db97281..2116859c383c9 100644 --- a/ext/date/lib/dow.c +++ b/ext/date/lib/dow.c @@ -74,6 +74,36 @@ timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d) return timelib_day_of_week_ex(y, m, d, 1); } +/* Checks if the given date is a weekend (Saturday or Sunday) */ +int timelib_is_weekend(timelib_time *time) +{ + timelib_sll dow; + + /* Ensure time parts are up to date */ + if (!time->have_date) { + return 0; + } + + dow = timelib_day_of_week(time->y, time->m, time->d); + /* 0 = Sunday, 6 = Saturday */ + return (dow == 0 || dow == 6); +} + +/* Checks if the given date is a weekday (Monday to Friday) */ +int timelib_is_weekday(timelib_time *time) +{ + timelib_sll dow; + + /* Ensure time parts are up to date */ + if (!time->have_date) { + return 0; + } + + dow = timelib_day_of_week(time->y, time->m, time->d); + /* 1 = Monday through 5 = Friday */ + return (dow>= 1 && dow <= 5); +} + /* jan feb mar apr may jun jul aug sep oct nov dec */ static int d_table_common[13] = { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; static int d_table_leap[13] = { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index a2c976af7ed9c..f03561109a231 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -464,6 +464,12 @@ timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d); /* Calculates the day of the ISO week from y, m, and d. 1=Monday, 7=Sunday */ timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d); +/* Checks if the given date is a weekend (Saturday or Sunday) */ +int timelib_is_weekend(timelib_time *time); + +/* Checks if the given date is a weekday (Monday to Friday) */ +int timelib_is_weekday(timelib_time *time); + /* Calculates the day of the year according to y-m-d. 0=Jan 1st..364/365=Dec * 31st */ timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d); diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e69512cedb440..22165ffe03d22 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2809,6 +2809,62 @@ PHP_METHOD(DateTimeImmutable, createFromTimestamp) } /* }}} */ +/* {{{ Checks if the given date is a weekend (Saturday or Sunday) */ +PHP_METHOD(DateTime, isWeekend) +{ + php_date_obj *dateobj; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(ZEND_THIS); + DATE_CHECK_INITIALIZED(dateobj->time, Z_OBJCE_P(ZEND_THIS)); + + RETURN_BOOL(timelib_is_weekend(dateobj->time)); +} +/* }}} */ + +/* {{{ Checks if the given date is a weekday (Monday to Friday) */ +PHP_METHOD(DateTime, isWeekday) +{ + php_date_obj *dateobj; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(ZEND_THIS); + DATE_CHECK_INITIALIZED(dateobj->time, Z_OBJCE_P(ZEND_THIS)); + + RETURN_BOOL(timelib_is_weekday(dateobj->time)); +} +/* }}} */ + +/* {{{ Checks if the given date is a weekend (Saturday or Sunday) */ +PHP_METHOD(DateTimeImmutable, isWeekend) +{ + php_date_obj *dateobj; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(ZEND_THIS); + DATE_CHECK_INITIALIZED(dateobj->time, Z_OBJCE_P(ZEND_THIS)); + + RETURN_BOOL(timelib_is_weekend(dateobj->time)); +} +/* }}} */ + +/* {{{ Checks if the given date is a weekday (Monday to Friday) */ +PHP_METHOD(DateTimeImmutable, isWeekday) +{ + php_date_obj *dateobj; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(ZEND_THIS); + DATE_CHECK_INITIALIZED(dateobj->time, Z_OBJCE_P(ZEND_THIS)); + + RETURN_BOOL(timelib_is_weekday(dateobj->time)); +} +/* }}} */ + static bool php_date_initialize_from_hash(php_date_obj **dateobj, const HashTable *myht) { zval *z_date; diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index 0b151c9d42163..3ae6e6d9c75e8 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -328,6 +328,12 @@ public function __wakeup(): void; public function __serialize(): array; public function __unserialize(array $data): void; + + /** @tentative-return-type */ + public function isWeekend(): bool; + + /** @tentative-return-type */ + public function isWeekday(): bool; } class DateTime implements DateTimeInterface @@ -445,6 +451,12 @@ public function getTimestamp(): int {} * @alias date_diff */ public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval {} + + /** @tentative-return-type */ + public function isWeekend(): bool {} + + /** @tentative-return-type */ + public function isWeekday(): bool {} } class DateTimeImmutable implements DateTimeInterface @@ -552,6 +564,12 @@ public static function createFromMutable(DateTime $object): static {} /** @return static */ public static function createFromInterface(DateTimeInterface $object): DateTimeImmutable {} // TODO return type should be static + + /** @tentative-return-type */ + public function isWeekend(): bool {} + + /** @tentative-return-type */ + public function isWeekday(): bool {} } class DateTimeZone diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index 5b583772e6582..a75e7cc28b4af 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -253,6 +253,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface___unseri ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface_isWeekend, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_DateTimeInterface_isWeekday arginfo_class_DateTimeInterface_isWeekend + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, datetime, IS_STRING, 0, "\"now\"") ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null") @@ -342,6 +347,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_DateTime_diff arginfo_class_DateTimeInterface_diff +#define arginfo_class_DateTime_isWeekend arginfo_class_DateTimeInterface_isWeekend + +#define arginfo_class_DateTime_isWeekday arginfo_class_DateTimeInterface_isWeekend + #define arginfo_class_DateTimeImmutable___construct arginfo_class_DateTime___construct #define arginfo_class_DateTimeImmutable___serialize arginfo_timezone_abbreviations_list @@ -423,6 +432,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_createFro ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0) ZEND_END_ARG_INFO() +#define arginfo_class_DateTimeImmutable_isWeekend arginfo_class_DateTimeInterface_isWeekend + +#define arginfo_class_DateTimeImmutable_isWeekday arginfo_class_DateTimeInterface_isWeekend + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeZone___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, timezone, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -576,6 +589,8 @@ ZEND_METHOD(DateTime, modify); ZEND_METHOD(DateTime, sub); ZEND_METHOD(DateTime, getMicrosecond); ZEND_METHOD(DateTime, setMicrosecond); +ZEND_METHOD(DateTime, isWeekend); +ZEND_METHOD(DateTime, isWeekday); ZEND_METHOD(DateTimeImmutable, __construct); ZEND_METHOD(DateTimeImmutable, __serialize); ZEND_METHOD(DateTimeImmutable, __unserialize); @@ -593,6 +608,8 @@ ZEND_METHOD(DateTimeImmutable, setTimestamp); ZEND_METHOD(DateTimeImmutable, setMicrosecond); ZEND_METHOD(DateTimeImmutable, createFromMutable); ZEND_METHOD(DateTimeImmutable, createFromInterface); +ZEND_METHOD(DateTimeImmutable, isWeekend); +ZEND_METHOD(DateTimeImmutable, isWeekday); ZEND_METHOD(DateTimeZone, __construct); ZEND_METHOD(DateTimeZone, __serialize); ZEND_METHOD(DateTimeZone, __unserialize); @@ -678,6 +695,8 @@ static const zend_function_entry class_DateTimeInterface_methods[] = { ZEND_RAW_FENTRY("__wakeup", NULL, arginfo_class_DateTimeInterface___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_RAW_FENTRY("__serialize", NULL, arginfo_class_DateTimeInterface___serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_RAW_FENTRY("__unserialize", NULL, arginfo_class_DateTimeInterface___unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) + ZEND_RAW_FENTRY("isWeekend", NULL, arginfo_class_DateTimeInterface_isWeekend, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) + ZEND_RAW_FENTRY("isWeekday", NULL, arginfo_class_DateTimeInterface_isWeekday, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_FE_END }; @@ -707,6 +726,8 @@ static const zend_function_entry class_DateTime_methods[] = { ZEND_ME(DateTime, setMicrosecond, arginfo_class_DateTime_setMicrosecond, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("getTimestamp", zif_date_timestamp_get, arginfo_class_DateTime_getTimestamp, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("diff", zif_date_diff, arginfo_class_DateTime_diff, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_ME(DateTime, isWeekend, arginfo_class_DateTime_isWeekend, ZEND_ACC_PUBLIC) + ZEND_ME(DateTime, isWeekday, arginfo_class_DateTime_isWeekday, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -736,6 +757,8 @@ static const zend_function_entry class_DateTimeImmutable_methods[] = { ZEND_ME(DateTimeImmutable, setMicrosecond, arginfo_class_DateTimeImmutable_setMicrosecond, ZEND_ACC_PUBLIC|ZEND_ACC_NODISCARD) ZEND_ME(DateTimeImmutable, createFromMutable, arginfo_class_DateTimeImmutable_createFromMutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DateTimeImmutable, createFromInterface, arginfo_class_DateTimeImmutable_createFromInterface, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(DateTimeImmutable, isWeekend, arginfo_class_DateTimeImmutable_isWeekend, ZEND_ACC_PUBLIC) + ZEND_ME(DateTimeImmutable, isWeekday, arginfo_class_DateTimeImmutable_isWeekday, ZEND_ACC_PUBLIC) ZEND_FE_END }; From 6d4116362cc99db9c180e7993ab04aa8f0f9ee14 Mon Sep 17 00:00:00 2001 From: xentixar Date: Sat, 6 Sep 2025 14:48:29 +0545 Subject: [PATCH 2/3] Add tests for DateTime::isWeekday() and DateTime::isWeekend() functionality --- ext/date/tests/DateTime_isWeekday_basic.phpt | 64 +++++++++++++++ ext/date/tests/DateTime_isWeekend_basic.phpt | 52 ++++++++++++ ...eTime_isWeekend_isWeekday_inheritance.phpt | 80 +++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 ext/date/tests/DateTime_isWeekday_basic.phpt create mode 100644 ext/date/tests/DateTime_isWeekend_basic.phpt create mode 100644 ext/date/tests/DateTime_isWeekend_isWeekday_inheritance.phpt diff --git a/ext/date/tests/DateTime_isWeekday_basic.phpt b/ext/date/tests/DateTime_isWeekday_basic.phpt new file mode 100644 index 0000000000000..a9f91fb732674 --- /dev/null +++ b/ext/date/tests/DateTime_isWeekday_basic.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test DateTime::isWeekday() function : basic functionality +--FILE-- +isWeekday()); + +// Sunday (weekend) +$date = new DateTime("2025-09-07"); +echo "Sunday 2025年09月07日 is weekday: "; +var_dump($date->isWeekday()); + +// Monday (weekday) +$date = new DateTime("2025-09-08"); +echo "Monday 2025年09月08日 is weekday: "; +var_dump($date->isWeekday()); + +// Tuesday (weekday) +$date = new DateTime("2025-09-09"); +echo "Tuesday 2025年09月09日 is weekday: "; +var_dump($date->isWeekday()); + +// Test with DateTimeImmutable +echo "\n*** Testing DateTimeImmutable::isWeekday() : basic functionality ***\n"; + +// Saturday (weekend) +$date = new DateTimeImmutable("2025-09-06"); +echo "Saturday 2025年09月06日 is weekday: "; +var_dump($date->isWeekday()); + +// Sunday (weekend) +$date = new DateTimeImmutable("2025-09-07"); +echo "Sunday 2025年09月07日 is weekday: "; +var_dump($date->isWeekday()); + +// Monday (weekday) +$date = new DateTimeImmutable("2025-09-08"); +echo "Monday 2025年09月08日 is weekday: "; +var_dump($date->isWeekday()); + +// Tuesday (weekday) +$date = new DateTimeImmutable("2025-09-09"); +echo "Tuesday 2025年09月09日 is weekday: "; +var_dump($date->isWeekday()); +?> +--EXPECT-- +*** Testing DateTime::isWeekday() : basic functionality *** +Saturday 2025年09月06日 is weekday: bool(false) +Sunday 2025年09月07日 is weekday: bool(false) +Monday 2025年09月08日 is weekday: bool(true) +Tuesday 2025年09月09日 is weekday: bool(true) + +*** Testing DateTimeImmutable::isWeekday() : basic functionality *** +Saturday 2025年09月06日 is weekday: bool(false) +Sunday 2025年09月07日 is weekday: bool(false) +Monday 2025年09月08日 is weekday: bool(true) +Tuesday 2025年09月09日 is weekday: bool(true) diff --git a/ext/date/tests/DateTime_isWeekend_basic.phpt b/ext/date/tests/DateTime_isWeekend_basic.phpt new file mode 100644 index 0000000000000..df9e31720ab64 --- /dev/null +++ b/ext/date/tests/DateTime_isWeekend_basic.phpt @@ -0,0 +1,52 @@ +--TEST-- +Test DateTime::isWeekend() function : basic functionality +--FILE-- +isWeekend()); + +// Sunday (weekend) +$date = new DateTime("2025-09-07"); +echo "Sunday 2025年09月07日 is weekend: "; +var_dump($date->isWeekend()); + +// Monday (weekday) +$date = new DateTime("2025-09-08"); +echo "Monday 2025年09月08日 is weekend: "; +var_dump($date->isWeekend()); + +// Test with DateTimeImmutable +echo "\n*** Testing DateTimeImmutable::isWeekend() : basic functionality ***\n"; + +// Saturday (weekend) +$date = new DateTimeImmutable("2025-09-06"); +echo "Saturday 2025年09月06日 is weekend: "; +var_dump($date->isWeekend()); + +// Sunday (weekend) +$date = new DateTimeImmutable("2025-09-07"); +echo "Sunday 2025年09月07日 is weekend: "; +var_dump($date->isWeekend()); + +// Monday (weekday) +$date = new DateTimeImmutable("2025-09-08"); +echo "Monday 2025年09月08日 is weekend: "; +var_dump($date->isWeekend()); +?> +--EXPECT-- +*** Testing DateTime::isWeekend() : basic functionality *** +Saturday 2025年09月06日 is weekend: bool(true) +Sunday 2025年09月07日 is weekend: bool(true) +Monday 2025年09月08日 is weekend: bool(false) + +*** Testing DateTimeImmutable::isWeekend() : basic functionality *** +Saturday 2025年09月06日 is weekend: bool(true) +Sunday 2025年09月07日 is weekend: bool(true) +Monday 2025年09月08日 is weekend: bool(false) diff --git a/ext/date/tests/DateTime_isWeekend_isWeekday_inheritance.phpt b/ext/date/tests/DateTime_isWeekend_isWeekday_inheritance.phpt new file mode 100644 index 0000000000000..41200e078f573 --- /dev/null +++ b/ext/date/tests/DateTime_isWeekend_isWeekday_inheritance.phpt @@ -0,0 +1,80 @@ +--TEST-- +Test DateTimeInterface::isWeekend() and DateTimeInterface::isWeekday() : inheritance functionality +--FILE-- +format('w'); + return ($day === 0 || $day === 6); + } + + #[\ReturnTypeWillChange] + public function isWeekday() + { + // Custom implementation that returns the same result + $day = (int)$this->format('w'); + return ($day>= 1 && $day <= 5); + } +} + +// Test with inherited class +echo "\nTesting MyDateTime (extends DateTime):\n"; +$date1 = new MyDateTime("2025-09-06"); // Saturday +echo "Saturday 2025-09-06 is weekend: "; +var_dump($date1->isWeekend()); +echo "Saturday 2025年09月06日 is weekday: "; +var_dump($date1->isWeekday()); + +$date2 = new MyDateTime("2025-09-08"); // Monday +echo "Monday 2025年09月08日 is weekend: "; +var_dump($date2->isWeekend()); +echo "Monday 2025年09月08日 is weekday: "; +var_dump($date2->isWeekday()); + +// Test with custom class extending DateTime with overridden methods +echo "\nTesting MyCustomDateTime (extends DateTime with overrides):\n"; +$date3 = new MyCustomDateTime("2025-09-06"); // Saturday +echo "Saturday 2025年09月06日 is weekend: "; +var_dump($date3->isWeekend()); +echo "Saturday 2025年09月06日 is weekday: "; +var_dump($date3->isWeekday()); + +$date4 = new MyCustomDateTime("2025-09-08"); // Monday +echo "Monday 2025年09月08日 is weekend: "; +var_dump($date4->isWeekend()); +echo "Monday 2025年09月08日 is weekday: "; +var_dump($date4->isWeekday()); + +?> +--EXPECT-- +*** Testing DateTimeInterface::isWeekend() and DateTimeInterface::isWeekday() with inheritance *** + +Testing MyDateTime (extends DateTime): +Saturday 2025年09月06日 is weekend: bool(true) +Saturday 2025年09月06日 is weekday: bool(false) +Monday 2025年09月08日 is weekend: bool(false) +Monday 2025年09月08日 is weekday: bool(true) + +Testing MyCustomDateTime (extends DateTime with overrides): +Saturday 2025年09月06日 is weekend: bool(true) +Saturday 2025年09月06日 is weekday: bool(false) +Monday 2025年09月08日 is weekend: bool(false) +Monday 2025年09月08日 is weekday: bool(true) From 19770dbcfe379bc05f959286742e3fc6667fa8b3 Mon Sep 17 00:00:00 2001 From: xentixar Date: Sat, 6 Sep 2025 15:05:57 +0545 Subject: [PATCH 3/3] Regenerate php_date_arginfo.h after rebase --- ext/date/php_date_arginfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index a75e7cc28b4af..9d8da4fc3f585 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 16d118b58a713bbea5174c170129aa9f6206de68 */ + * Stub hash: 6a68b81e360c8e91dfe44d7783356f48f2948f20 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)

AltStyle によって変換されたページ (->オリジナル) /