简体   繁体   English

Google格式的日期与格式比较在Google Apps脚本中落后1天

[英]Date comparisons with formatDate in Google Apps Script are 1 day behind

Writing a Google Apps Script that looks at tasks via the Google Tasks API (as an Advanced Service) and checks their due date to see if they are overdue. 编写Google Apps脚本,以通过Google Tasks API(作为高级服务)查看任务,并检查其到期日期,以查看是否过期。 If they are, it should then move them to the current day. 如果是,则应将其移至当天。

Completed Project 完成项目

I used this code to create this project for keeping Google Tasks up to date: 我使用以下代码创建了此项目,以使Google任务保持最新状态:

Keep Google Tasks Updated 保持Google任务更新

Issue 问题

When comparing the current day with the date the task is due, the date the task is due is always one day behind. 当将当前日期与任务到期日进行比较时,任务到期日总是滞后一天。

Research 研究

Looking into it I found that it could have to do with Daylight Savings Time and just one hour off could mean the difference in two days. 研究它,我发现它可能与夏时制有关,仅休息一小时就意味着两天的时间差。 I found this question that had a similar issue, their solution was to use Session.getScriptTimeZone() to set the timezone correctly. 我发现这个问题也有类似的问题,他们的解决方案是使用Session.getScriptTimeZone()正确设置时区。

However even when I set the timezone using Session.getScriptTimeZone() it still has the task's due date one day behind. 但是,即使当我使用Session.getScriptTimeZone()设置时区时,它的任务的截止日期仍要晚一天。

The Code 编码

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.');
  }
}

Logs 日志

[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

=== [ UPDATE ] === === [更新] ===

I noticed that if I log the original task.due it appears to have the correct date. 我注意到,如果我记录原始task.due ,则该日期似乎正确。 So something about the formatting is changing the date. 因此,有关格式的某些事情正在更改日期。

New Code 新密码

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.');
  }
}

New Logs 新日志

[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

=== [ Update 2 ] === === [更新2] ===

Changed both "EST" in formatDate to Session.getScriptTimeZone() 将formatDate中的"EST"都更改为Session.getScriptTimeZone()

Removed .valueOf() for comparison. 删除了.valueOf()以进行比较。

Still results in the same issue 仍然导致相同的问题

New Code 新密码

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.');
  }
}

New Logs 新日志

[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

Per Google Tasks API documentation, the task#due property is an RFC 3339 datetime value, eg "2018-04-11T0:45:26.000Z" . 根据Google Tasks API文档, task#due属性RFC 3339日期时间值,例如"2018-04-11T0:45:26.000Z" From this string, you can construct a Javascript Date natively, ie 从这个字符串,您可以本地构造一个Javascript Date ,即

var taskDueDate = new Date(task.due);

Note that this is equivalent to calling Date.parse() and thus could be the reason your date comparisons fail, given that Google Apps Script is Javascript 1.6 (ie not ES5+). 请注意,这等效于调用Date.parse() ,因此,鉴于Google Apps脚本是Javascript 1.6(即非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 . 假设您知道从task.due获得的严格的特定格式,那么使用自定义解析器可能是更好的方法。 One such parser is detailed in this answer . 此答案中有一个这样的解析器。

As @Serge mentions, you should perform this comparison using native Date objects, and not Strings : @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;
}

for info, this is a small code I use to convert RFC339 time to date object. 对于信息,这是一个小代码,用于将RFC339时间转换为日期对象。 I find it easier to read and understand. 我发现它更容易阅读和理解。

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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM