【问题标题】:Google Apps Script and RFC 3339 issueGoogle Apps 脚本和 RFC 3339 问题
【发布时间】:2016-03-31 21:29:00
【问题描述】:

Google reference documentation 中,我找到了一个将 RFC3339 日期字符串转换为有效日期对象的简短函数。代码非常简单,如下所示:

function parseDate(string) {
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  return new Date(parts.join(' '));
}

问题是它不起作用。(我很惊讶他们发布了一个不起作用的代码......我错过了什么吗?)

我在使用 JSON 对日期进行字符串化和解析时也遇到了问题,因为 JSON 方法返回一个 UTC 值(最后是一个 Z),因此我丢失了时区信息。 Google 的代码也不处理这个问题(即使它有效)。

下面是我用来测试它的演示代码和我为得到我想要的东西而编写的解决方案。不确定它是否非常有效或写得好,但至少我得到了我想要的结果(我在设置为 GMT+2,比利时夏令时的脚本中执行此代码)。 我愿意接受任何改进此代码的建议。(这将是这个问题的主题)

我在代码中添加了很多日志和cmets,以使其尽可能清晰:

function testJSONDate() {
  Logger.log('starting value : "2016/3/31 12:00:00"');
  var jsDate = JSON.stringify(new Date("2016/3/31 12:00:00"));// time is 12:00 I'm in GMT+2
  Logger.log('JSON.stringify value : '+jsDate);
  Logger.log('JSON parse jsDate : '+JSON.parse(jsDate)); // time is 10:00, UTC
  var jsDateWithoutQuotes = jsDate.replace(/"/,'');
  var date = parseDate(jsDateWithoutQuotes); 
  Logger.log('parsed RFC3339 date using Google\'s code : '+date);  // does not return a valid date
  var otherFunction = parseDate2(jsDateWithoutQuotes);
  Logger.log('parsed RFC3339 date using other code : '+otherFunction); // does return a valid date in my TZ
}

function parseDate(string) {
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  return new Date(parts.join(' '));
}
function parseDate2(string) {
  var refStr = new Date().toString();
  var fus = Number(refStr.substr(refStr.indexOf('GMT')+4,2));
  Logger.log('TZ offset = '+fus);
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  var t = parts[1].split(':');
  return new Date(new Date(parts[0]).setHours(+t[0]+fus,+t[1],0));
}

记录器结果:


在第一个答案后编辑

在代码稍作改动后,我设法让 Google 的 sn-p 工作,但由于 JSON 转换 JS 日期对象的方式,时区丢失的问题仍然存在。

下面的新代码和记录器结果:

function testJSONDate() {
  Logger.log('starting value : 2016/3/31 12:00:00');
  var jsDate = JSON.stringify(new Date("2016/3/31 12:00:00"));// time is 12:00 I'm in GMT+2
  Logger.log('JSON.stringify value : '+jsDate);
  Logger.log('JSON parse jsDate : '+JSON.parse(jsDate)); // time is 10:00, UTC
  var jsDateWithoutQuotesAndMillisecAndZ = jsDate.replace(/"/g,'').split('.')[0];
  Logger.log('jsDateWithoutQuotesAndMillisecAndZ = '+jsDateWithoutQuotesAndMillisecAndZ);
  var date = parseDate(jsDateWithoutQuotesAndMillisecAndZ); 
  Logger.log('parsed RFC3339 date using Google\'s code : '+date);  // does not return a valid date
  var otherFunction = parseDate2(jsDateWithoutQuotesAndMillisecAndZ);
  Logger.log('parsed RFC3339 date using other code : '+otherFunction); // does return a valid date in the right tz
}

【问题讨论】:

    标签: google-apps-script


    【解决方案1】:

    您已经断章取义地使用了一个小辅助函数。它只是一种权宜之计,可以让特定 API (Google Calendar API) 返回的字符串在 Apps 脚本中正确解析。它不是任何一种通用日期转换器。一个项目成员在filing an issue 时将它放在一起,并且该线程中的后续消息指出了该函数无法处理的另一个细节。

    截至目前,Apps Script 中的日期解析器可以正确解析以下格式:

    function testdate() {
      Logger.log(new Date("2016/03/31 10:00:00"));       // local time
      Logger.log(new Date("2016/03/31 10:00:00 +2:00")); // with given offset
      Logger.log(new Date("2016-03-31T08:00:00.000Z"));  // in UTC 
    }
    

    请注意,UTC 时间戳需要毫秒,但其他时间不允许。

    您对需要解析但不是上述之一的日期时间字符串执行的操作取决于其格式。如果您有 2016-03-31T10:00:00(显然,这是 Google Calendar API 返回的内容)并且这意味着在本地时间,那么您需要引用的解析函数所做的事情:用空格替换 T 和 - 由 /。如果相同的字符串表示UTC时间,则需要在末尾添加.000Z。等等。

    【讨论】:

    • 感谢您的回答,我不知道存在 TZ 时不允许毫秒的限制(很抱歉忘记了 g),但除此之外,简单的 JSON 字符串化/解析过程有效日期对象仍在擦除 tz 信息。另外,我不将它用于日历服务,而是在 gs 脚本和 htmlService 客户端 JavaScript 之间交换数据。我会用新的代码版本更新问题。
    • 这种JSON.stringify 行为绝不是Apps 脚本特有的。这就是 JavaScript 中 JSON.stringify works 的方式:它存储 date.toISOString()。这个想法是捕获的是时间点,而不是发送者的时区。如果您喜欢不同的字符串格式,this post 提供了使用 moment.js 的解决方案。您还可以使用字符串操作从date.toString() 自己生成诸如字符串。
    • 这就是我在上面的代码中所做的。谢谢你的反馈,我会接受你的回答。
    猜你喜欢
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    相关资源
    最近更新 更多