I have a web page with a script that fetches and displays some event times, using @date-fns/tz to show the time in the event's time zone (Eastern) rather than the browser's local time zone. If I set my system time zone to e.g. Pacific, the page works correctly and an event beginning at 12 pm Eastern shows "12 pm". However, I am running into an issue where Google indexes the page and shows "9 am" in the search results (Googlebot appears to use Pacific time). This is a problem because a user may search for the event details and read the incorrect time from the result summary without clicking to see the correct time on the full page.
Here's an example project: https://stackblitz.com/edit/vitejs-vite-seugjghv?file=main.js
Assuming your system time zone is Pacific, you should see the following correct output:
localTZ: America/Los_Angeles
targetTZ: America/New_York
isoStr: 2026-05-24T12:00:00-04:00
parsed: Sun May 24 2026 09:00:00 GMT-0700 (Pacific Daylight Time)
asTz: Sun May 24 2026 12:00:00 GMT-0400 (Eastern Daylight Time)
asTz.internal: Sun May 24 2026 05:00:00 GMT-0700 (Pacific Daylight Time)
resTz: America/New_York
resOffset: 240
But if you build the project and put it on the web, and use a tool to preview Google's view, you will get a strange result:
localTZ: America/Los_Angeles
targetTZ: America/New_York
isoStr: 2026-05-24T12:00:00-04:00
parsed: Sun May 24 2026 09:00:00 GMT-0700 (Pacific Daylight Time)
asTz: Sun May 24 2026 09:00:00 GMT-0700 (Pacific Daylight Time)
asTz.internal: Sat Apr 25 2026 12:35:08 GMT-0700 (Pacific Daylight Time)
resTz: America/New_York
resOffset: 420
The timezone adjusted TZDate still shows the local time. The internal date object is set to the current date, and not the input date. The TZDate's .timeZone property is correctly set to America/New_York, but .getTimezoneOffset() returns the offset for Pacific.
I spent some time poking at it, and the only explanation I can think of is that Googlebot's JS implementation does not respect the prototype chain when invoking methods of Date subclasses, meaning that tzDate.setTime() invokes the default method from the Date class. You can add a console.log to the TZDateMini's setTime implementation to see that it never gets called, even if TZDateMini.prototype.setTime != Date.prototype.setTime. Explicitly calling TZDateMini.prototype.setTime.apply(tzDate, ...) does appear to work, however.
I understand this isn't really a bug with @date-fns/tz, but SEO is incredibly important for many developers and we will need to either figure out a workaround or use a different library unless Google can change its crawling engine.
I have a web page with a script that fetches and displays some event times, using @date-fns/tz to show the time in the event's time zone (Eastern) rather than the browser's local time zone. If I set my system time zone to e.g. Pacific, the page works correctly and an event beginning at 12 pm Eastern shows "12 pm". However, I am running into an issue where Google indexes the page and shows "9 am" in the search results (Googlebot appears to use Pacific time). This is a problem because a user may search for the event details and read the incorrect time from the result summary without clicking to see the correct time on the full page.
Here's an example project: https://stackblitz.com/edit/vitejs-vite-seugjghv?file=main.js
Assuming your system time zone is Pacific, you should see the following correct output:
But if you build the project and put it on the web, and use a tool to preview Google's view, you will get a strange result:
The timezone adjusted TZDate still shows the local time. The internal date object is set to the current date, and not the input date. The TZDate's .timeZone property is correctly set to America/New_York, but .getTimezoneOffset() returns the offset for Pacific.
I spent some time poking at it, and the only explanation I can think of is that Googlebot's JS implementation does not respect the prototype chain when invoking methods of Date subclasses, meaning that tzDate.setTime() invokes the default method from the Date class. You can add a console.log to the TZDateMini's setTime implementation to see that it never gets called, even if TZDateMini.prototype.setTime != Date.prototype.setTime. Explicitly calling TZDateMini.prototype.setTime.apply(tzDate, ...) does appear to work, however.
I understand this isn't really a bug with @date-fns/tz, but SEO is incredibly important for many developers and we will need to either figure out a workaround or use a different library unless Google can change its crawling engine.