Datetime 处理日期/时间和时区的奇怪时间偏移

Datetime 处理日期/时间和时区的奇怪时间偏移,datetime,google-apps-script,google-sheets,timezone,timezone-offset,Datetime,Google Apps Script,Google Sheets,Timezone,Timezone Offset,我一直在尝试编写一些函数,根据谷歌电子表格上多个单元格的信息创建谷歌日历和谷歌日历事件 发布的第一个问题的日期部分已经解决 现在我在时间部分遇到了问题 以下代码: var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Passeios"); var timeStart = ss.getRange(6,4).getValue(); var timeEnd = ss.getRange(6,5).getValue();

我一直在尝试编写一些函数,根据谷歌电子表格上多个单元格的信息创建谷歌日历和谷歌日历事件

发布的第一个问题的日期部分已经解决

现在我在时间部分遇到了问题

以下代码:

  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Passeios");
  var timeStart = ss.getRange(6,4).getValue();
  var timeEnd = ss.getRange(6,5).getValue();
  var ssTZ = SpreadsheetApp.getActive().getSpreadsheetTimeZone();

  Logger.log("timeStart: " + timeStart );
  Logger.log("timeEnd: " + timeEnd);


  var dateStart = ss.getRange(6,8).getValue();

  var dateStartObj = new Date(Utilities.formatDate(dateStart, 'ssTZ' , 'MMMM dd, yyyy HH:mm:ss Z'));

var timeStartObj= new Date(Utilities.formatDate(timeStart, 'ssTZ' , 'MMMM dd, yyyy HH:mm:ss Z'));

var justTimeStart = Utilities.formatDate(timeStart, ssTZ, 'HH:mm');


Logger.log(" Time Start Object: " + timeStartObj);
Logger.log("Time Start Object Hours: " + timeStartObj.getHours());
Logger.log("Time Start Object Minutes: " + timeStartObj.getMinutes());

Logger.log("Start Time HH:mm: " + justTimeStart)

var hourStart = Utilities.formatDate(timeStart, ssTZ, 'HH');
var minutesStart = Utilities.formatDate(timeStart, ssTZ, 'mm');
var hourEnd = Utilities.formatDate(timeEnd, ssTZ, 'HH');
var minutesEnd = Utilities.formatDate(timeEnd, ssTZ, 'mm');


Logger.log(" TimeZone :" + ssTZ);
Logger.log(hourStart);
Logger.log(minutesStart);
Logger.log(hourEnd);
Logger.log(minutesEnd);  
生成以下日志

时间开始:1899年12月30日星期六07:06:28 GMT-0300(BRT)

时间结束:1899年12月30日星期六07:36:28 GMT-0300(BRT)

时间开始对象:1899年12月30日星期六07:06:28 GMT-0300(BRT)

时间开始对象小时数:7

时间开始对象分钟数:6

开始时间HH:mm:07:00

时区:美洲/圣保罗

07

00

07

三十

电子表格单元格的格式为HH:mm,并显示 07:00开始时间 07:30结束时间

正如您所看到的,在记录单元格值或使用单元格值构造Date()对象时,有大约6分28秒的偏移量,我不确定从何而来

将单元格的格式设置为仅小时或仅分钟或HH:mm不带该偏移量

编辑

我注意到Date()构造函数的ssTZ变量位于单引号之间,因此它可能会被丢弃,因为它不应被识别为有效时区

不确定它使用了什么,但实际的电子表格时区和错误引用的时区之间的差异似乎是28秒,我也不知道它们来自哪里

6分钟的偏移量仍然存在,您可以检查以下代码和日志打印

  var timeStart = ss.getRange(6,4).getValue();
  var ssTZ = SpreadsheetApp.getActive().getSpreadsheetTimeZone();

var timeStartObj1= new Date(Utilities.formatDate(timeStart, 'ssTZ' , 'MMMM dd, yyyy HH:mm:ss Z'));
var timeStartObj2= new Date(Utilities.formatDate(timeStart, ssTZ , 'MMMM dd, yyyy HH:mm:ss Z'));
var justTimeStart = Utilities.formatDate(timeStart, ssTZ, 'HH:mm');

  Logger.log("timeStart: " + timeStart );
  Logger.log(" Time Start Object1: " + timeStartObj1);
  Logger.log(" Time Start Object2: " + timeStartObj2);
  Logger.log("justTimeStart: " + justTimeStart)
时间开始:1899年12月30日星期六07:06:28 GMT-0300(BRT)

时间开始目标1:Sat Dec 30 1899 07:06:28 GMT-0300(BRT)

时间开始目标2:Sat Dec 30 1899 07:06:00 GMT-0300(BRT)

justTimeStart:07:00

编辑2

它与时区有关,可能由于1899年被解释为120年前的日期而进行了一些调整

使用以下构造函数时,在指定格式的字符串处不使用Z:

var timeStartObj3= new Date(Utilities.formatDate(timeStart, ssTZ , 'MMMM dd, yyyy HH:mm:ss'));
Logger.log(" Time Start Object3: " + timeStartObj3);
日志结果是:

时间开始目标3:Sat Dec 30 1899 07:00:00 GMT-0300(BRT)

编辑3

越来越奇怪

如果我在Logger.log调用中使用文本连接,我会得到一个不同的字符串,如果我仅使用var名称调用日志:

  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Passeios");
  var timeStart = ss.getRange(6,4).getValue();
  Logger.log("timeStart: " + timeStart);
  Logger.log(timeStart);
时间开始:1899年12月30日星期六07:06:28 GMT-0300(BRT)

12月30日星期六07:00:00 GMT-03:06 1899

我确实理解它实际上是同一时间的不同表示(我估计即使没有显示,也有28秒)

我的猜测是,无论是否使用连接,文本解析方法都有不同的行为(这至少令人困惑)

我仍然不知道06分28秒是从哪里来的,也不知道在使用单元格值中的时间和日期时如何确保一致性,而这些值只有日期或时间,并且必须混合使用


这真是令人困惑…

6分28秒来自圣保罗和格林尼治标准时间之间的(LMT)偏移:

LMT条目位于第一行。最后一列(1914年)是“截止日期”,这意味着在TZDB中,LMT在1914年之前一直在使用。之后,将应用区域条目中的下一条规则(
-3:00

LMT根据参考位置的经度和纬度计算。它与该区域当时可能使用的计时没有关系。在许多旧日期的情况下,没有历史信息可以知道时间是如何被保留那么久的

换句话说,您的示例日期是1899年,是在巴西已知的计时实践之前的一段时间,因此使用了当地的平均时间


使用一个更现代的日期,您应该会得到按照今天的标准对您更有意义的结果。

Google sheets将日期或时间单元格值存储为一个数字,对应于从1899年12月30日0:00:00开始的完整天数(或分数)

当处理只包含时间值的单元格时,
getValues()
函数将生成日期部分设置为12/30/1899的日期对象,但这将有一个相应的时区偏移量,它会在时间上创建奇数偏移量,如@Matt Johnson在上一个答案中所解释的

最大的问题是,对于不同的时区,该偏移量将不一致,因为该日期将为不同的位置/时区和不同的年份产生不同的偏移量,因此您需要解决一系列可能的情况

当尝试创建Date()对象时,这会产生不同的结果,因为有时偏移量作为时区偏移量传递,而有时它是实际时间值的一部分,具体取决于构造函数和文本解析的格式,这会造成很多混乱,从以下代码中可以看出:

var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Passeios");
var ssTZ = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var timeStart = ss.getRange(6,4).getValue();

var date1 = new Date(timeStart);
var date2 = new Date(Utilities.formatDate(timeStart, ssTZ , 'MMMM dd, yyyy HH:mm:ss Z'));
var date3 = new Date(Utilities.formatDate(timeStart, ssTZ , 'MMMM dd, yyyy HH:mm:ss'));

var date4 = new Date(Utilities.formatDate(timeStart, ssTZ , "yyyy-MM-dd'T'HH:mm:ss'Z'"));
     
  
Logger.log("date1: " + date1);
Logger.log("date2: " + date2);
Logger.log("date3: " + date3);
Logger.log("date4: " + date4);
生成此日志:

日期1:Sat Dec 30 1899 07:06:28 GMT-0300(BRT)

日期2:1899年12月30日星期六07:06:00 GMT-0300(BRT)

日期3:1899年12月30日星期六07:00:00 GMT-0300(BRT)

日期4:1899年12月30日星期六04:00:00 GMT-0300(BRT)

有时,时区偏移量会一起被忽略,而其他时候,只会忽略秒部分,而且它可能会按小时被解释为完全不同的时区。(该字符串格式取自
formatDate()

正如@TheMaster所建议的,这可能在电子表格上创建辅助单元格/列以添加更一致的日期部分时解决,但在动态处理此信息的情况下(在我的情况下,是来自多个关联表单的多个答案的多个查询结果的组合),这可能不实用

@TheMaster还建议的另一种方法可能是使用
getDisplayValues()
并解析文本,但如果disp
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Passeios");
var ssTZ = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var timeStart = ss.getRange(6,4).getValue();

var date1 = new Date(timeStart);
var date2 = new Date(Utilities.formatDate(timeStart, ssTZ , 'MMMM dd, yyyy HH:mm:ss Z'));
var date3 = new Date(Utilities.formatDate(timeStart, ssTZ , 'MMMM dd, yyyy HH:mm:ss'));

var date4 = new Date(Utilities.formatDate(timeStart, ssTZ , "yyyy-MM-dd'T'HH:mm:ss'Z'"));
     
  
Logger.log("date1: " + date1);
Logger.log("date2: " + date2);
Logger.log("date3: " + date3);
Logger.log("date4: " + date4);
var hours = Utilities.formatDate(timeStart, ssTZ, 'HH');
var minutes = Utilities.formatDate(timeStart, ssTZ, 'mm');

Logger.log("Hours: "+ hours);
Logger.log("Minutes: "+ minutes);