11<?php
2+ declare (strict_types=1 );
23
34namespace om ;
45
@@ -23,12 +24,7 @@ public function getArrayCopy(): array {
2324 * Return sorted EventList (the newest dates are first)
2425 */
2526 public function sorted (): EventsList {
26- $ this ->uasort (static function ($ a , $ b ): int {
27- if ($ a ['DTSTART ' ] === $ b ['DTSTART ' ]) {
28- return 0 ;
29- }
30- return ($ a ['DTSTART ' ] < $ b ['DTSTART ' ]) ? -1 : 1 ;
31- });
27+ $ this ->uasort ($ this ->comparator (true ));
3228
3329 return $ this ;
3430 }
@@ -37,14 +33,59 @@ public function sorted(): EventsList {
3733 * Return reversed sorted EventList (the oldest dates are first)
3834 */
3935 public function reversed (): EventsList {
40- $ this ->uasort (static function ($ a , $ b ): int {
41- if ($ a ['DTSTART ' ] === $ b ['DTSTART ' ]) {
36+ $ this ->uasort ($ this ->comparator (false ));
37+
38+ return $ this ;
39+ }
40+
41+ /**
42+ * Return a comparator callable for DTSTART values.
43+ * @param bool $ascending When true, sorts ascending (older first) like the original implementation; false inverts order.
44+ */
45+ private function comparator (bool $ ascending ): callable {
46+ return function ($ a , $ b ) use ($ ascending ): int {
47+ $ ad = $ a ['DTSTART ' ] ?? null ;
48+ $ bd = $ b ['DTSTART ' ] ?? null ;
49+
50+ // both equal (including both null)
51+ if ($ ad === $ bd ) {
4252 return 0 ;
4353 }
44- return ($ a ['DTSTART ' ] > $ b ['DTSTART ' ]) ? -1 : 1 ;
45- });
4654
47- return $ this ;
55+ // decide ordering for nulls: nulls sort last
56+ if ($ ad === null ) {
57+ return 1 ;
58+ }
59+ if ($ bd === null ) {
60+ return -1 ;
61+ }
62+
63+ $ at = $ this ->dtTimestamp ($ ad );
64+ $ bt = $ this ->dtTimestamp ($ bd );
65+
66+ if ($ at === $ bt ) {
67+ return 0 ;
68+ }
69+
70+ if ($ ascending ) {
71+ return ($ at < $ bt ) ? -1 : 1 ;
72+ }
73+ return ($ at > $ bt ) ? -1 : 1 ;
74+ };
75+ }
76+
77+ /**
78+ * Normalize a DTSTART value to an integer timestamp for stable comparisons.
79+ */
80+ private function dtTimestamp (mixed $ value ): int {
81+ if ($ value instanceof \DateTimeInterface) {
82+ return $ value ->getTimestamp ();
83+ }
84+ if (is_int ($ value ) || is_float ($ value ) || is_numeric ($ value )) {
85+ return (int ) $ value ;
86+ }
87+ $ ts = strtotime ((string ) $ value );
88+ return $ ts === false ? 0 : $ ts ;
4889 }
4990
5091}
0 commit comments