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. 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:
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.
However even when I set the timezone using Session.getScriptTimeZone()
it still has the task's due date one day behind.
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. 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 ] ===
Changed both "EST"
in formatDate to Session.getScriptTimeZone()
Removed .valueOf()
for comparison.
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, e.g."2018-04-11T0:45:26.000Z"
. From this string, you can construct a JavascriptDate
natively, i.e.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 (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 fromtask.due
. One such parser is detailed in this answer.As @Serge mentions, you should perform this comparison using native
Date
objects, and notStrings
:for info, this is a small code I use to convert RFC339 time to date object. I find it easier to read and understand.