与 Google Apps 脚本中的 formatDate 的日期比较落后 1 天
Date comparisons with formatDate in Google Apps Script are 1 day behind
编写一个 Google Apps 脚本,通过 Google 任务 API(作为高级服务)查看任务并检查它们的截止日期以查看它们是否过期。如果是,则应该将它们移到当天。
完成项目
我使用此代码创建此项目以保持 Google 任务最新:
问题
将当前日期与任务截止日期进行比较时,任务截止日期总是晚一天。
研究
调查后我发现它可能与夏令时有关,仅仅休息一小时可能意味着两天后的差异。我发现 有类似的问题,他们的解决方案是使用 Session.getScriptTimeZone()
正确设置时区。
然而,即使我使用 Session.getScriptTimeZone()
设置时区,任务的截止日期仍然晚了一天。
代码
function checkOverdue(t) {
var today = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
//var today = new Date();
var tasks = t;
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
if (task.due) {
var taskDue = Utilities.formatDate(new Date(task.due), "EST", "MM/dd/yyyy");
Logger.log('"%s", Comparing "%s" to "%s"',
task.title, taskDue, today);
if (taskDue.valueOf() < today.valueOf()) {
Logger.log('Task with title "%s" is past due', task.title);
}
}
}
} else {
Logger.log('No tasks found.');
}
}
日志
[18-04-10 13:12:33:927 EDT] "Create Bio presentation", Comparing "04/09/2018" to "04/10/2018"
[18-04-10 13:12:33:928 EDT] Task with title "Create Bio presentation" is past due
[18-04-10 13:12:33:929 EDT] "Bio Presentation", Comparing "04/10/2018" to "04/10/2018"
[18-04-10 13:12:33:930 EDT] "Matrix HW", Comparing "04/09/2018" to "04/10/2018"
[18-04-10 13:12:33:930 EDT] Task with title "Matrix HW" is past due
=== [更新] ===
我注意到如果我记录原始 task.due
它似乎有正确的日期。所以关于格式的一些事情正在改变日期。
新代码
function checkOverdue(t) {
var today = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
//var today = new Date();
var tasks = t;
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
if (task.due) {
var taskDue = Utilities.formatDate(new Date(task.due), "EST", "MM/dd/yyyy");
Logger.log('"%s", Comparing TaskDue: "%s" to today: "%s", task.due "%s"', task.title, taskDue, today, task.due);
if (taskDue.valueOf() < today.valueOf()) {
Logger.log('Task with title "%s" is past due', task.title);
}
}
}
} else {
Logger.log('No tasks found.');
}
}
新日志
[18-04-10 14:15:17:628 EDT] "Create Bio presentation", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 14:15:17:629 EDT] Task with title "Create Bio presentation" is past due
[18-04-10 14:15:17:630 EDT] "Bio Presentation", Comparing TaskDue: "04/10/2018" to today: "04/10/2018", task.due "2018-04-11T00:00:00.000Z"
[18-04-10 14:15:17:631 EDT] "Matrix HW", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 14:15:17:631 EDT] Task with title "Matrix HW" is past due
=== [更新 2] ===
将 formatDate 中的两个 "EST"
更改为 Session.getScriptTimeZone()
删除了 .valueOf()
以进行比较。
仍然导致相同的问题
新代码
function checkOverdue(t) {
var today = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy");
//var today = new Date();
var tasks = t;
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
if (task.due) {
var taskDue = Utilities.formatDate(new Date(task.due), Session.getScriptTimeZone(), "MM/dd/yyyy");
Logger.log('"%s", Comparing TaskDue: "%s" to today: "%s", task.due "%s"', task.title, taskDue, today, task.due);
if (taskDue < today) {
Logger.log('Task with title "%s" is past due', task.title);
}
}
}
} else {
Logger.log('No tasks found.');
}
}
新日志
[18-04-10 15:21:01:988 EDT] "Create Bio presentation", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 15:21:01:988 EDT] Task with title "Create Bio presentation" is past due
[18-04-10 15:21:01:990 EDT] "Bio Presentation", Comparing TaskDue: "04/10/2018" to today: "04/10/2018", task.due "2018-04-11T00:00:00.000Z"
[18-04-10 15:21:01:991 EDT] "Matrix HW", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 15:21:01:991 EDT] Task with title "Matrix HW" is past due
根据 Google 任务 API 文档,task#due
property is an RFC 3339 日期时间值,例如"2018-04-11T0:45:26.000Z"
。
从这个字符串中,您可以原生地构造一个 Javascript Date
,即
var taskDueDate = new Date(task.due);
请注意,这相当于调用 Date.parse()
and thus could be the reason your date comparisons fail, given that Google Apps Script is Javascript 1.6 (i.e. not ES5+). A possibly better method would be to use a custom parser, given that you know the strict specific format that you will get from task.due
. One such parser is detailed in this answer。
如 @Serge 所述,您应该使用本机 Date
对象执行此比较,而不是 Strings
:
function isOverdue(task) {
if(!task.due)
return false;
var now = new Date();
var endOfToday = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1)); // Also known as start of tomorrow ;)
var taskDueDate = myFunctionToConvertRFC3339StringToJSDate(task.due);
return taskDueDate < endOfToday;
}
有关信息,这是我用来将 RFC339 时间转换为日期对象的小代码。
我发现它更容易阅读和理解。
function parseDate_RFC3339(string) {
var refStr = new Date().toString();
Logger.log('refStr = '+refStr);
var tzOffset = Number(refStr.substr(refStr.indexOf('GMT')+4,2));
Logger.log('TZ offset = '+tzOffset);
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]+tzOffset,+t[1],0));
}
编写一个 Google Apps 脚本,通过 Google 任务 API(作为高级服务)查看任务并检查它们的截止日期以查看它们是否过期。如果是,则应该将它们移到当天。
完成项目
我使用此代码创建此项目以保持 Google 任务最新:
问题
将当前日期与任务截止日期进行比较时,任务截止日期总是晚一天。
研究
调查后我发现它可能与夏令时有关,仅仅休息一小时可能意味着两天后的差异。我发现 Session.getScriptTimeZone()
正确设置时区。
然而,即使我使用 Session.getScriptTimeZone()
设置时区,任务的截止日期仍然晚了一天。
代码
function checkOverdue(t) {
var today = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
//var today = new Date();
var tasks = t;
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
if (task.due) {
var taskDue = Utilities.formatDate(new Date(task.due), "EST", "MM/dd/yyyy");
Logger.log('"%s", Comparing "%s" to "%s"',
task.title, taskDue, today);
if (taskDue.valueOf() < today.valueOf()) {
Logger.log('Task with title "%s" is past due', task.title);
}
}
}
} else {
Logger.log('No tasks found.');
}
}
日志
[18-04-10 13:12:33:927 EDT] "Create Bio presentation", Comparing "04/09/2018" to "04/10/2018"
[18-04-10 13:12:33:928 EDT] Task with title "Create Bio presentation" is past due
[18-04-10 13:12:33:929 EDT] "Bio Presentation", Comparing "04/10/2018" to "04/10/2018"
[18-04-10 13:12:33:930 EDT] "Matrix HW", Comparing "04/09/2018" to "04/10/2018"
[18-04-10 13:12:33:930 EDT] Task with title "Matrix HW" is past due
=== [更新] ===
我注意到如果我记录原始 task.due
它似乎有正确的日期。所以关于格式的一些事情正在改变日期。
新代码
function checkOverdue(t) {
var today = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
//var today = new Date();
var tasks = t;
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
if (task.due) {
var taskDue = Utilities.formatDate(new Date(task.due), "EST", "MM/dd/yyyy");
Logger.log('"%s", Comparing TaskDue: "%s" to today: "%s", task.due "%s"', task.title, taskDue, today, task.due);
if (taskDue.valueOf() < today.valueOf()) {
Logger.log('Task with title "%s" is past due', task.title);
}
}
}
} else {
Logger.log('No tasks found.');
}
}
新日志
[18-04-10 14:15:17:628 EDT] "Create Bio presentation", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 14:15:17:629 EDT] Task with title "Create Bio presentation" is past due
[18-04-10 14:15:17:630 EDT] "Bio Presentation", Comparing TaskDue: "04/10/2018" to today: "04/10/2018", task.due "2018-04-11T00:00:00.000Z"
[18-04-10 14:15:17:631 EDT] "Matrix HW", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 14:15:17:631 EDT] Task with title "Matrix HW" is past due
=== [更新 2] ===
将 formatDate 中的两个 "EST"
更改为 Session.getScriptTimeZone()
删除了 .valueOf()
以进行比较。
仍然导致相同的问题
新代码
function checkOverdue(t) {
var today = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy");
//var today = new Date();
var tasks = t;
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
if (task.due) {
var taskDue = Utilities.formatDate(new Date(task.due), Session.getScriptTimeZone(), "MM/dd/yyyy");
Logger.log('"%s", Comparing TaskDue: "%s" to today: "%s", task.due "%s"', task.title, taskDue, today, task.due);
if (taskDue < today) {
Logger.log('Task with title "%s" is past due', task.title);
}
}
}
} else {
Logger.log('No tasks found.');
}
}
新日志
[18-04-10 15:21:01:988 EDT] "Create Bio presentation", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 15:21:01:988 EDT] Task with title "Create Bio presentation" is past due
[18-04-10 15:21:01:990 EDT] "Bio Presentation", Comparing TaskDue: "04/10/2018" to today: "04/10/2018", task.due "2018-04-11T00:00:00.000Z"
[18-04-10 15:21:01:991 EDT] "Matrix HW", Comparing TaskDue: "04/09/2018" to today: "04/10/2018", task.due "2018-04-10T00:00:00.000Z"
[18-04-10 15:21:01:991 EDT] Task with title "Matrix HW" is past due
根据 Google 任务 API 文档,task#due
property is an RFC 3339 日期时间值,例如"2018-04-11T0:45:26.000Z"
。
从这个字符串中,您可以原生地构造一个 Javascript Date
,即
var taskDueDate = new Date(task.due);
请注意,这相当于调用 Date.parse()
and thus could be the reason your date comparisons fail, given that Google Apps Script is Javascript 1.6 (i.e. not ES5+). A possibly better method would be to use a custom parser, given that you know the strict specific format that you will get from task.due
. One such parser is detailed in this answer。
如 @Serge 所述,您应该使用本机 Date
对象执行此比较,而不是 Strings
:
function isOverdue(task) {
if(!task.due)
return false;
var now = new Date();
var endOfToday = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1)); // Also known as start of tomorrow ;)
var taskDueDate = myFunctionToConvertRFC3339StringToJSDate(task.due);
return taskDueDate < endOfToday;
}
有关信息,这是我用来将 RFC339 时间转换为日期对象的小代码。 我发现它更容易阅读和理解。
function parseDate_RFC3339(string) {
var refStr = new Date().toString();
Logger.log('refStr = '+refStr);
var tzOffset = Number(refStr.substr(refStr.indexOf('GMT')+4,2));
Logger.log('TZ offset = '+tzOffset);
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]+tzOffset,+t[1],0));
}