@@ -59,12 +59,62 @@ static void test_time_close_hourly() {
5959 CHECK (tc == to + 3600000 - 1 );
6060}
6161
62+ // --- 2-arg time(tf, tz): a timezone passed in the session slot ---
63+
64+ static void test_time_tz_in_session_slot_equiv () {
65+ std::printf (" test_time_tz_in_session_slot_equiv\n " );
66+ // time("D", "America/New_York") binds the tz into the session slot. The
67+ // engine must reinterpret it as the timezone (not a session) — previously
68+ // it treated it as a session, matched no HHMM window, and returned na.
69+ int64_t bar = 1775572200000LL ; // 2026-04-07 14:30 UTC = 10:30 NY (EDT)
70+ int64_t two_arg = pine_time (bar, " D" , " America/New_York" , " " , " 15" );
71+ int64_t three_arg = pine_time (bar, " D" , " " , " America/New_York" , " 15" );
72+ CHECK (!is_na (two_arg)); // was na for every bar (the bug)
73+ CHECK (two_arg == three_arg); // reinterpreted identically to the 3-arg form
74+ }
75+
76+ static void test_time_tz_in_session_daily_change () {
77+ std::printf (" test_time_tz_in_session_daily_change\n " );
78+ // Bars in the same NY-day share the daily time; the next NY-day differs —
79+ // this is what makes ta.change(time("D", tz)) fire once per day.
80+ int64_t bar_a = 1775572200000LL ; // 2026-04-07 10:30 NY
81+ int64_t bar_b = bar_a + 3600000LL ; // +1h, same NY-day
82+ int64_t bar_next = bar_a + 24LL * 3600000LL ; // +24h, next NY-day
83+ int64_t ta = pine_time (bar_a, " D" , " America/New_York" , " " , " 15" );
84+ int64_t tb = pine_time (bar_b, " D" , " America/New_York" , " " , " 15" );
85+ int64_t tn = pine_time (bar_next, " D" , " America/New_York" , " " , " 15" );
86+ CHECK (ta == tb); // same day: no change
87+ CHECK (ta != tn); // new day: change fires
88+ }
89+
90+ static void test_time_real_session_2arg_still_filters () {
91+ std::printf (" test_time_real_session_2arg_still_filters\n " );
92+ // A genuine 2-arg session (no tz) must still filter — the reinterpretation
93+ // only triggers for tz-looking strings, never "0800-1600".
94+ int64_t bar_in = 1775572200000LL ; // 14:30 UTC — inside 0800-1600 UTC
95+ int64_t bar_out = 1775601000000LL ; // 22:30 UTC — outside
96+ CHECK (!is_na (pine_time (bar_in, " 60" , " 0800-1600" , " " , " 60" )));
97+ CHECK ( is_na (pine_time (bar_out, " 60" , " 0800-1600" , " " , " 60" )));
98+ }
99+
100+ static void test_time_gmt_in_session_slot () {
101+ std::printf (" test_time_gmt_in_session_slot\n " );
102+ // GMT/UTC specifiers in the session slot are also recognized as timezones.
103+ int64_t bar = 1775572200000LL ;
104+ CHECK (!is_na (pine_time (bar, " D" , " GMT+0" , " " , " 15" )));
105+ CHECK (!is_na (pine_time (bar, " D" , " UTC" , " " , " 15" )));
106+ }
107+
62108int main () {
63109 test_time_hourly_bucket_utc ();
64110 test_time_session_ny_inside ();
65111 test_time_session_ny_outside ();
66112 test_time_weekday_filter_mon_fri_only ();
67113 test_time_close_hourly ();
114+ test_time_tz_in_session_slot_equiv ();
115+ test_time_tz_in_session_daily_change ();
116+ test_time_real_session_2arg_still_filters ();
117+ test_time_gmt_in_session_slot ();
68118
69119 std::printf (" session_time: %d passed, %d failed\n " , tests_passed, tests_failed);
70120 return tests_failed > 0 ? 1 : 0 ;
0 commit comments