通过Google Apps脚本比较日期的繁琐问题

时间:2016-07-08 12:23:17

标签: javascript datetime google-apps-script google-sheets custom-function

今天我遇到了使用GAS比较两个日期的问题:currentDate包含今天的日期,scheduledDate包含放在列中的日期,该日期被确定为row[3]

我已经花了5个小时(希望我不走运),在我们开始之前,首先要描述的是scheduledDate中的单元格是如何填充的:使用自定义函数(代码放在下面) =SubtractDaysFromDate('2016'!A54, 8),它从位于8的日期中减去'2016'!A54天,并将单元格中的结果显示为08/07/201608.07.2016(取决于您如何设置查看格式)。

以下是=SubtractDaysFromDate()源代码:

function SubtractDaysFromDate(date, d) {
  var output = new Date(date.getTime()-d*(24*3600*1000)); // d — количество вычитаемых дней, date — дата или ячейка с датой, из которой вычитается данное количество дней.
  return output;
}

以下是我的脚本的源代码:

function SendElectronicMailing() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = "Рассылка"; // Здесь указывается название листа в таблице.
var sheet = ss.getSheetByName(sheetName);
var startRow = 2; // Здесь первая строка для отправки рассылки.
var numRows = sheet.getLastRow()-1; // Здесь количество строк, которые необходимо обработать для отправки рассылки.
var dataRange = sheet.getRange(startRow, 1, numRows, 6);
var data = dataRange.getValues();
/* Здесь переменные с тематическими рассылками. */
var mailingChildrenHealth = "Здоровье детей перед отдыхом";
var mailingNonPersonalized = "–";
/* Здесь переменные со статусами электропочтовых рассылок. */
var statusMailingAwaiting = "Рассылка ожидает отправки";
var statusMailingSent = "Рассылка отправлена";
var statusMailingNotRequired = "Рассылка не требуется";
  for (var i = 0; i < data.length; ++i) {
    var row = data[i];
    var currentDate = new Date();
    var scheduledDate = new Date(row[3]); // Здесь указывается столбец с назначенной датой для отправки электропочтовой рассылки.
    var formattedCurrentDate = Utilities.formatDate(currentDate, "GMT+0300", "dd.MM.yyyy");
    Logger.log(currentDate);
    var formattedScheduledDate = Utilities.formatDate(scheduledDate, "GMT+0300", "dd.MM.yyyy");
    Logger.log("Getting new Date(): " + scheduledDate);
    Logger.log("Getting plain row[3]: " + row[3]);
    Logger.log("Using toString() and after replace(): " + row[3].toString().replace(/\./g, "/"));
    Logger.log("Using valueOf() of row[3]: " + scheduledDate.valueOf());
    var bookingNumber = [i+2];
    var contactFullName = row[0];
    var contactGivenName = contactFullName.split(" ").slice(0, -1).join(" ");
    var contactEmail = row[1];
    var mailingTopic = row[2];
    var cheapTicketsFinderLink = "http://go.ruslanchik.ru/";
    var mailingStatus = row[4]; // Столбец, в котором выставляется статус отправки/неотправки писем электропочтовой рассылки.
    var senderName = "Наталья Селецкая (Мини-гостиница Бердянская 56)";
    var replyTo = "natalya@berdyanskaya56.ru";
    Logger.log(formattedCurrentDate + " ==? " + formattedScheduledDate);


        /* Выставление статуса «Рассылка не требуется» для бронирований, по которым ввиду своего скудоумия не смог настроить отправку рассылки. */
        if (currentDate.valueOf() > scheduledDate.valueOf() && mailingStatus == statusMailingAwaiting) {
        sheet.getRange(startRow + i, 5).setValue(statusMailingNotRequired);
        Logger.log("Выставлен статус " + "«" + statusMailingNotRequired + "»" + " электропочтовой рассылки для бронирования № " + bookingNumber + " (" + contactFullName + ")" + " по причине несвоевременности её отправки гостю.");
        }

        /* Тематическая рассылка для гостей с детьми («забота о здоровье детей») с общей рассылкой о дешёвых билетах в Ейск и обратно. */
        if (formattedCurrentDate == formattedScheduledDate && mailingTopic == mailingChildrenHealth && mailingStatus == statusMailingAwaiting) {
        /* Здесь рассылка о здоровье детей перед отдыхом. */
        var subject_children_health = "Email subject";
        var message_children_health = "Email body.";
        MailApp.sendEmail(contactEmail, subject_children_health, message_children_health, {name: senderName, replyTo: replyTo});
        /* Здесь рассылка о дешёвых билетах в Ейск и обратно для гостей с детьми. */
        var subject_cheap_tickets = "Email subject";
        var message_cheap_tickets = "Email body";
        MailApp.sendEmail(contactEmail, subject_cheap_tickets, message_cheap_tickets, {name: senderName, replyTo: replyTo});
        /* А здесь уже проставление статуса отправки. */
        sheet.getRange(startRow + i, 5).setValue(statusMailingSent);
        Logger.log("Отправлены тематическая и общая электропочтовые рассылки для бронирования № " + bookingNumber + " (" + contactFullName + ")" + " гостю на " + contactEmail + ".");
        }
        SpreadsheetApp.flush(); // Здесь завершается обновление ячеек 5-го столбца, в котором проставляется статус отправки электропочтовых рассылок гостям.
  }
}

要检查输入,请转到上面的链接,检查名为2016的工作表(从此工作表=SubtractDatesFromDate()获取要删除的日期)以及{{ 1}}(在此表上我的脚本运行)。

要继续,我的脚本会在名为Рассылка的工作表上浏览具有这些减去日期(=SubtractDaysFromDate())的所有单元格,并检查当前日期是否等于Рассылка(即,

表示包含此表中scheduledDate的所有单元格的列)。

问题是虽然=SubtractDaysFromDate()中的一小部分日期(由scheduledDate生成)被正确识别,但其中的另一部分却无法识别并检索为=SubtractDaysFromDate()

为了说明问题,这里是脚本日志:

01.01.1970

如果你仔细阅读上面的代码,很明显,对于某些日期,比较效果很好:

[16-07-08 14:31:40:171 EAT] 08.07.2016 ==? 01.01.1970
[16-07-08 14:31:40:172 EAT] Fri Jul 08 14:31:40 GMT+03:00 2016
[16-07-08 14:31:40:173 EAT] Getting new Date(): Fri Jun 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:173 EAT] Getting plain row[3]: Fri Jun 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:174 EAT] Using toString() and after replace(): Fri Jun 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:175 EAT] Using valueOf() of row[3]: 1464901200000
[16-07-08 14:31:40:175 EAT] 08.07.2016 ==? 03.06.2016
[16-07-08 14:31:40:176 EAT] Fri Jul 08 14:31:40 GMT+03:00 2016
[16-07-08 14:31:40:177 EAT] Getting new Date(): Wed Aug 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:178 EAT] Getting plain row[3]: Wed Aug 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:178 EAT] Using toString() and after replace(): Wed Aug 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:179 EAT] Using valueOf() of row[3]: 1470171600000
[16-07-08 14:31:40:179 EAT] 08.07.2016 ==? 03.08.2016
[16-07-08 14:31:40:181 EAT] Fri Jul 08 14:31:40 GMT+03:00 2016
[16-07-08 14:31:40:181 EAT] Getting new Date(): Invalid Date
[16-07-08 14:31:40:182 EAT] Getting plain row[3]: #ERROR!
[16-07-08 14:31:40:182 EAT] Using toString() and after replace(): #ERROR!
[16-07-08 14:31:40:183 EAT] Using valueOf() of row[3]: NaN
[16-07-08 14:31:40:183 EAT] 08.07.2016 ==? 01.01.1970

对于其他部分,它不会:

[16-07-08 14:31:40:176 EAT] Fri Jul 08 14:31:40 GMT+03:00 2016 (note: this a current date)
[16-07-08 14:31:40:177 EAT] Getting new Date(): Wed Aug 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:178 EAT] Getting plain row[3]: Wed Aug 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:178 EAT] Using toString() and after replace(): Wed Aug 03 2016 00:00:00 GMT+0300 (MSK)
[16-07-08 14:31:40:179 EAT] Using valueOf() of row[3]: 1470171600000
[16-07-08 14:31:40:179 EAT] 08.07.2016 ==? 03.08.2016

为了更好的未知,这里是我的GS表的链接:https://docs.google.com/spreadsheets/d/1azDfWZWDSVTVVKLaJZlsRDbW21-Cps8Hx8M2kbclw-g/edit?pli=1#gid=2147296153

拜托,您能否检查一下是否有任何重要信息让它正常工作?为什么[16-07-08 14:31:40:181 EAT] Fri Jul 08 14:31:40 GMT+03:00 2016 (note: this a current date) [16-07-08 14:31:40:181 EAT] Getting new Date(): Invalid Date [16-07-08 14:31:40:182 EAT] Getting plain row[3]: #ERROR! [16-07-08 14:31:40:182 EAT] Using toString() and after replace(): #ERROR! [16-07-08 14:31:40:183 EAT] Using valueOf() of row[3]: NaN [16-07-08 14:31:40:183 EAT] 08.07.2016 ==? 01.01.1970 计算的日期的一部分被我的脚本正确识别,另一部分和其中最重要的部分不是?

我该如何解决?我们非常感谢所有以结果为导向的尝试来解决这个问题。

<小时/> 已编辑。这是我已编辑的代码的一部分:

=SubtractDatesFromDate()

Mu问题是如何在function SendElectronicMailing1() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var bookingsSheetName = "2016"; // Здесь указывается название листа откуда брать даты заезда по бронированиям. var mailingSheetName = "M1"; // Здесь указывается название листа где обновлять статусы отправки электропочтовой рассылки. var bookingsTableSheet = ss.getSheetByName(bookingsSheetName); var mailingListSheet = ss.getSheetByName(mailingSheetName); var startRow = 2; // Здесь первая строка для отправки рассылки. var bookingsNumRows = bookingsTableSheet.getLastRow()-1; // Здесь количество строк, которые необходимо обработать для отправки рассылки. var mailingNumRows = mailingListSheet.getLastRow()-1; var bookingsDataRange = bookingsTableSheet.getRange(startRow, 1, bookingsNumRows, 2); var mailingDataRange = mailingListSheet.getRange(startRow, 1, mailingNumRows, 6); var bookingsData = bookingsDataRange.getValues(); var mailingData = mailingDataRange.getValues(); /* Здесь переменные с тематическими рассылками. */ var mailingChildrenHealth = "Здоровье детей перед отдыхом"; var mailingNonPersonalized = "–"; /* Здесь переменные со статусами электропочтовых рассылок. */ var statusMailingAwaiting = "Рассылка ожидает отправки"; var statusMailingSent = "Рассылка отправлена"; var statusMailingNotRequired = "Рассылка не требуется"; for (var i = 0; i < bookingsData.length; ++i) { var row = bookingsData[i]; var currentDate = new Date(); var scheduledDate = new Date(row[0]).setHours(0,0,0,0)+(-10*24*3600*1000); // Здесь указывается столбец с назначенной датой для отправки электропочтовой рассылки. Её еще можно считать через new Date().setHours(0,0,0,0)+(-10*24*3600*1000). var formattedCurrentDate = Utilities.formatDate(currentDate, "GMT+0300", "dd.MM.yyyy"); Logger.log("It is a current date: " + currentDate); var formattedScheduledDate = Utilities.formatDate(scheduledDate, "GMT+0300", "dd.MM.yyyy"); Logger.log("Getting new Date() of row " + [i+2] + ": " + scheduledDate); Logger.log("Getting clear value of row " + [i+2] + ": " + row[3]); Logger.log("Using toString() and after replace(): " + [i+2] + ": " + row[3].toString().replace(/\./g, "/")); Logger.log("Using valueOf() of row " + [i+2] + ": " + scheduledDate.valueOf()); var bookingNumber = [i+2]; var contactFullName = row[0]; var contactGivenName = contactFullName.split(" ").slice(0, -1).join(" "); var contactEmail = row[1]; var mailingTopic = mailingData.row[2]; var cheapTicketsFinderLink = "http://go.ruslanchik.ru/"; var mailingStatus = row[4]; // Столбец, в котором выставляется статус отправки/неотправки писем электропочтовой рассылки. var senderName = "Наталья Селецкая (Мини-гостиница Бердянская 56)"; var replyTo = "natalya@berdyanskaya56.ru"; Logger.log(formattedCurrentDate + " ==? " + formattedScheduledDate); } } 工作表中获取row[2]的值,并将其写入Рассылка链接到for (var i = 0; i < bookingsData.length; ++i) {的变量?这是使用2016的正确方法吗?

1 个答案:

答案 0 :(得分:0)

这非常愚蠢,可能无法解决问题,但是,我发现GAS有时很挑剔。通常我只会做一次性的事情,但因为我不能自己编辑脚本......

尝试向左移动'('因此它在d周围。我知道操作的顺序应该处理这个,但它可能没有,那么你会遇到一个严重的问题。我想不出还有什么会仅在某些日期导致问题,除非电子表格中的日期格式不正确,这似乎不是。所以,而不是这样:

var output = new Date(date.getTime()-d*(24*3600*1000));

尝试:

var output = new Date(date.getTime()-(d*24*3600*1000));

编辑:

这显然不是你所追求的,但它显示了在同一个SS上的两张纸之间转移细胞。

function example() {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet1 = ss.getActiveSheet();
  var sheet2 = ss.getSheetByName('sheet2');

  var startRow = 1;
  var numRows = sheet1.getLastRow()-1; 
  var dataRange = sheet1.getRange(startRow, 1, numRows, 6);
  var data = dataRange.getValues();

  var row = []

  for (var i in data) {
    row.push(data[i] + 10);
  }

  sheet2.appendRow(row);
}