mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	bug fix: Check offsets when browser doesn't canonicalize.
This is more of a workaround than a bug fix. Some JS implementations are less "aggressive" about canonicalizing things like America/Montreal to America/Toronto. We instead use offset checks.
This commit is contained in:
		@@ -555,18 +555,44 @@ export function should_display_profile_incomplete_alert(timestamp: number): bool
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function browser_canonicalize_timezone(uncanonicalized_timezone: string): string {
 | 
			
		||||
export function get_time_in_timezone(date: Date, timezone: string): number {
 | 
			
		||||
    return Date.parse(date.toLocaleString("en-US", {timeZone: timezone}));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function get_offset_difference_at_date(
 | 
			
		||||
    timezone1: string,
 | 
			
		||||
    timezone2: string,
 | 
			
		||||
    reference_date: Date,
 | 
			
		||||
): number {
 | 
			
		||||
    const date1 = get_time_in_timezone(reference_date, timezone1);
 | 
			
		||||
    const date2 = get_time_in_timezone(reference_date, timezone2);
 | 
			
		||||
    return date1 - date2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function are_timezones_on_same_clock_now(timezone1: string, timezone2: string): boolean {
 | 
			
		||||
    // America/Los_Angeles is clearly the same as America/Los_Angeles:
 | 
			
		||||
    if (timezone1 === timezone2) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We still want this function to return true if the timezones are
 | 
			
		||||
    // on the same clock for now, even though they may eventually diverge
 | 
			
		||||
    // during Daylight Savings. This avoids nagging the user.  The only
 | 
			
		||||
    // tradeoff is if the user stays logged on while the clocks change,
 | 
			
		||||
    // but that should be rare.
 | 
			
		||||
    const now = new Date();
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        // we use the runtime's default locale, to match _browser_time_zone_.
 | 
			
		||||
        const canonicalized_timezone = new Intl.DateTimeFormat(undefined, {
 | 
			
		||||
            timeZone: uncanonicalized_timezone,
 | 
			
		||||
        }).resolvedOptions().timeZone;
 | 
			
		||||
        return canonicalized_timezone;
 | 
			
		||||
        return get_offset_difference_at_date(timezone1, timezone2, now) === 0;
 | 
			
		||||
    } catch {
 | 
			
		||||
        return "";
 | 
			
		||||
        // This should only happen during testing, but we just catch any error
 | 
			
		||||
        // related to invalid time zones.
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function is_browser_timezone_same_as(uncanonicalized_target_timezone: string): boolean {
 | 
			
		||||
    return browser_time_zone() === browser_canonicalize_timezone(uncanonicalized_target_timezone);
 | 
			
		||||
export function is_browser_timezone_same_as(zulip_time_zone: string): boolean {
 | 
			
		||||
    // We delegate most of this check to facilitate testing.
 | 
			
		||||
    // We don't want to mock browser_time_zone.
 | 
			
		||||
    return are_timezones_on_same_clock_now(browser_time_zone(), zulip_time_zone);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -654,6 +654,40 @@ run_test("should_display_profile_incomplete_alert", () => {
 | 
			
		||||
    assert.equal(timerender.should_display_profile_incomplete_alert(realm_date_created_secs), true);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
run_test("are_timezones_on_same_clock_now", () => {
 | 
			
		||||
    assert.ok(
 | 
			
		||||
        timerender.are_timezones_on_same_clock_now("America/Los_Angeles", "America/Los_Angeles"),
 | 
			
		||||
    );
 | 
			
		||||
    assert.ok(timerender.are_timezones_on_same_clock_now("America/New_York", "America/New_York"));
 | 
			
		||||
 | 
			
		||||
    // Montreal and Toronto are equivalent year-round.
 | 
			
		||||
    assert.ok(timerender.are_timezones_on_same_clock_now("America/Montreal", "America/Toronto"));
 | 
			
		||||
 | 
			
		||||
    assert.ok(
 | 
			
		||||
        !timerender.are_timezones_on_same_clock_now("Invalid/Timezone", "America/Los_Angeles"),
 | 
			
		||||
    );
 | 
			
		||||
    assert.ok(
 | 
			
		||||
        !timerender.are_timezones_on_same_clock_now("America/New_York", "America/Los_Angeles"),
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
run_test("are_timezones_on_same_clock_now (Phoenix)", () => {
 | 
			
		||||
    /*
 | 
			
		||||
        If you live in Phoenix and make the short flight to Los Angeles during
 | 
			
		||||
        Daylight Savings time, you don't need to reset your watch.
 | 
			
		||||
 | 
			
		||||
        Likewise, during the winter, if you go to Denver, you don't need to
 | 
			
		||||
        reset your watch.
 | 
			
		||||
 | 
			
		||||
        We err on the side of not nagging Phoenix folks to change their
 | 
			
		||||
        "Zulip clock" for these short trips.
 | 
			
		||||
    */
 | 
			
		||||
    assert.ok(
 | 
			
		||||
        timerender.are_timezones_on_same_clock_now("America/Phoenix", "America/Los_Angeles") ||
 | 
			
		||||
            timerender.are_timezones_on_same_clock_now("America/Phoenix", "America/Denver"),
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
run_test("is_browser_timezone_same_as", () => {
 | 
			
		||||
    assert.equal(timerender.is_browser_timezone_same_as(timerender.browser_time_zone()), true);
 | 
			
		||||
 | 
			
		||||
@@ -661,19 +695,13 @@ run_test("is_browser_timezone_same_as", () => {
 | 
			
		||||
    assert.equal(timerender.is_browser_timezone_same_as("Invalid/Timezone"), false);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
run_test("test time zone math", () => {
 | 
			
		||||
    // This test doesn't seem to test any Zulip code, but it seems
 | 
			
		||||
    // useful to keep around anyway, since the offset logic
 | 
			
		||||
    // here is useful to understand.
 | 
			
		||||
 | 
			
		||||
run_test("time zone helpers", () => {
 | 
			
		||||
    function get_time_in_timezone(date, timezone) {
 | 
			
		||||
        return Date.parse(date.toLocaleString("en-US", {timeZone: timezone}));
 | 
			
		||||
        return timerender.get_time_in_timezone(date, timezone);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function get_offset_difference_at_date(tz1, tz2, reference_date) {
 | 
			
		||||
        const date1 = get_time_in_timezone(reference_date, tz1);
 | 
			
		||||
        const date2 = get_time_in_timezone(reference_date, tz2);
 | 
			
		||||
        return date1 - date2;
 | 
			
		||||
        return timerender.get_offset_difference_at_date(tz1, tz2, reference_date);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The current time in America/Phoenix does equal the current time
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user