添加到 Google 日历渲染 link 不显示用户当地时间

Add to Google Calendar render link not showing user's local time

我可以使用此 link 到 google 日历创建活动。 但是我认为时间已经到了 UTC(比我想要参加活动的时间提前 5.30 小时)

示例: This link 将创建一个事件,但它显示的时间是从中午 12 点 30 分到下午 4 点。 此事件应该是早上 6.30 点到上午 10 点。

According to this link,从时间字符串中删除 Z 应该在事件中设置用户的本地时间。

to use the user's timezone: 20201231T193000/20201231T223000 (don't specify a timezone);

to use UTC timezone, convert datetime to UTC, then use Z suffix: 20201231T193000Z/20201231T223000Z;

我也尝试过 this link 的相同解决方案,但事件时间仍然没有到来。它在 link.

中转换
const startDateTimeFormattedGoogle = eventStartDateTime ? eventStartDateTime.format(
        "YYYYMMDDTHHmmss"
      ) : null;
      const endDateTimeFormattedGoogle = eventEndDateTime ? eventEndDateTime.format(
        "YYYYMMDDTHHmmss"
      ) : null;
      const addToGoogleLink = `https://calendar.google.com/calendar/render?action=TEMPLATE&dates=${startDateTimeFormattedGoogle}/${endDateTimeFormattedGoogle}&location=${data.location}&text=${data.title}`;

更新:

console.log(88888, moment(eventStartDateTime).format('YYYYMMDDTHHmmssZ'),
result: 88888 20210430T123000+00:00 20210430T160000+00:00

console.log(111111, moment(eventStartDateTime).format('YYYYMMDDTHHmmss'),
        moment(eventEndDateTime).format('YYYYMMDDTHHmmss'))
result : 111111 20210430T123000 20210430T160000

result url: https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20210430T123000+00:00/20210430T160000+00:00&location=Calgary, Downtown&text=The 2020 Festival

时区不是这样运作的。当您从字符串中删除 "Zulu time"(+00:00 偏移量,即 UTC)后缀时,区域设置感知系统将使用您提供的时间 。这导致显示的时间与提供的时间相同:

Offset Raw Value Locale-unaware Locale-aware
+03:00 20210430T123000 2021-04-30 12:30:00 2021-04-30 12:30:00

如果保留后缀,则表示您提供的时间采用协调世界时(或 UTC)格式。然后时间由区域设置感知系统进行相应调整,例如 Google Calendar(前提是用户没有禁用时区调整):

Offset Raw Value Locale-unaware Locale-aware
+03:00 20210430T123000Z 2021-04-30 12:30:00 2021-04-30 15:30:00

接下来,YYYYMMDDTHHmmSSZ 是一个有效的 Moment.js format string,所以你应该直接插入它,令牌语义开始发挥作用:

Token Repetitions Meaning Example
Y 4 Long (4-digit) year format 2021
M 2 Short month format, padded to 2 digits if necessary 01..12
D 2 Day of Month format, padded to 2 digits if necessary 01..31
T 1 literal T, no special formatting meaning, so no need to escape T
H 2 24-hour hour format, padded to 2 digits if necessary 00..23
m 2 Minutes format, padded to 2 digits if necessary 00..59
S 2 Fractional seconds format 00..99
Z 1 Time Zone, sign + 4 digits without colon +0000, -0000

如您所料,YYYYMMDDTHHmmssZ 格式字符串避免了“小数秒”警告,但 Z 未转义,因此被视为时区指示符。根据文档,这可以通过适当的转义来解决:

To escape characters in format strings, you can wrap the characters in square brackets.

你自己试试看(仅供参考,既然你用的是Moment.js,如果不是严格强制你用,别用,是officially deprecated in favour of other libraries until the Temporal proposal发货):

(() => {
  const data = {
    location: "Calgary, Downtown",
    title: "The 2020 Festival"
  };

  const eventStartDateTime = new Date();
  const eventEndDateTime = new Date();

  const startDateTimeFormatted = moment(eventStartDateTime).format("YYYYMMDDTHHmmss[Z]");
  const endDateTimeFormatted = moment(eventEndDateTime).format("YYYYMMDDTHHmmss[Z]");

  const link = `https://calendar.google.com/calendar/render?action=TEMPLATE&dates=${startDateTimeFormatted}/${endDateTimeFormatted}&location=${data.location}&text=${data.title}`;

  const anchor = document.createElement("p");
  anchor.textContent = link;

  document.body.append(anchor);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>