18

我一直在这个圈子上转圈...我有一个包含两个日期的电子表格,我需要找到两者之间经过的年数(即某人在给定日期的年龄;这是Excel 的 DATEDIF 的替代品)。

第一步是将 Google 的序列号转换为 JS Date 对象,但似乎没有执行此操作的 Date 构造函数。有任何想法吗?

谢谢。

4

8 回答 8

16

To convert a Google spreadsheet date to a javascript date :

var JSdate = Date.parse(Cell.getValue())

To convert a javascript date to a Google spreadsheet date:

function GoogleDate( JSdate ) { 
   var D = new Date(JSdate) ;
   var Null = new Date(Date.UTC(1899,11,30,0,0,0,0)) ; // the starting value for Google
   return ((D.getTime()  - Null.getTime())/60000 - D.getTimezoneOffset()) / 1440 ;
}
于 2017-01-14T22:41:50.543 回答
11

我知道您对目前的解决方案很满意,但我只是想补充一下我对 Google Apps 脚本如何处理“日期”的观察,这些“日期”可以通过自定义函数传递,也可以使用 getValue() 从单元格中检索。

我的经验法则是,如果 Sheets(电子表格应用程序)提供格式为日期的值(通过自动强制或用户设置格式),则 Google Apps 脚本会自动将此值保存为日期对象。

例如:

function returnDate(value) {
  return new Date(value);  
}

如果您1/1/13在 A1 中输入,并在另一个单元格中调用=returnDate(A1),它将返回相同的日期(就像您只是return value;在代码中一样)。但是,请注意当您将 A1 格式化为“正常”(将其转换为数值)时会发生什么。在这里,“表格序列号”(从 1899 年 12 月 30 日开始的天数)被 Google Apps 脚本转换为日期对象,但在 GAS 中,它被“视为”从 1970 年 1 月 1 日午夜开始的毫秒数. 因此,如果您传递您认为代表日期的数值,您可能会得到意想不到的结果。

还比较:

=returnDate(DATE(2013;1;1))

=returnDate(VALUE("1/1/13"))

=returnDate(DATEVALUE("1/1/13"))

=returnDate("1/1/13")

=returnDate("1/1/2013")

后两个“工作”,因为new Date()成功地从有效字符串创建日期对象,但请注意,Sheets 自动强制转换为当前世纪,而 GAS 将两位数年份强制转换为 1900 年代。

因此,IMO 如果您希望它的行为与 Excel 中的行为完全相同(即“将”数值“视为”日期的序列号),则需要首先测试传递的参数是否为日期对象(或“有效的”文本字符串),如果不是,则以数学方式将其从“从 1899 年 12 月 30 日开始的天数”转换为“从 1970 年 1 月 1 日开始的毫秒数”,然后再转换new Date()

为冗长的帖子道歉。

于 2013-01-16T20:36:16.923 回答
7

这就是我所做的:

function numberToDate(number){
  var date = new Date(number * 24 * 60 * 60 * 1000);
  date.setFullYear(date.getFullYear() - 70);
  date.setDate(date.getDate() - 1);
  return (date);
}

这可能看起来有点脏,但这是我目前找到的唯一解决方案

于 2016-10-25T13:12:09.423 回答
1

经过更多的实验,结果证明它确实有效,这有点令人惊讶。new Date(cell)似乎在内部将序列号转换为足以创建日期对象的字符串。完整答案:

function datedif(first, second, format) {
  var e1  = new Date(first);
  var e2  = new Date(second);
  var age = e2.getFullYear() - e1.getFullYear();
  if(
      (e2.getMonth() <  e1.getMonth()) || 
     ((e2.getMonth() == e1.getMonth()) && (e2.getDate() < e1.getDate())))
    age--;
  return age;
}
于 2013-01-16T17:12:47.320 回答
0

你可以这样尝试:

return new Date(1900, 0, --excelDate)
于 2018-05-25T05:45:18.900 回答
0

为我工作

private static getDateFromGoogle(serialNumber: number): Date {
  // Google     30 Dec 1899
  // Javascript 01 Jan 1970
  return new Date((serialNumber - 25569) * 86400000);
}

于 2022-02-28T14:40:18.607 回答
0

首先,您必须从 google sheet config 获取时区设置。

然后,这是完美的解决方案:

import { zonedTimeToUtc, utcToZonedTime } from "date-fns-tz";

const SheetDate = {
  origin: Date.UTC(1899, 11, 30, 0, 0, 0, 0),
  dayToMs: 24 * 60 * 60 * 1000
};
function serialToDate(d: number, sheetTimeZone: string): Date {
  return zonedTimeToUtc(
    new Date(d * SheetDate.dayToMs + SheetDate.origin),
    sheetTimeZone
  );
}
function dateToSerial(date: Date, sheetTimeZone: string) {
  const msec = utcToZonedTime(date, sheetTimeZone).getTime() - SheetDate.origin;
  return msec / SheetDate.dayToMs;
}
于 2020-11-13T01:56:23.633 回答
-2

通过“序列号”,我猜您是在谈论从纪元开始以秒或毫秒为单位的 unix 时间。您可以简单地使用标准的 Javascript Date 对象:

new Date(value);

谷歌是你的朋友。这里有一些参考资料可以帮助您入门:

Javascript 允许您对两个日期进行简单的减法运算,以毫秒为单位返回时间差。

var timeDiffInMS = date2 - date1;

这应该是你需要弄清楚的全部,所以我将把年份计算留给读者作为练习。

于 2013-01-16T17:12:16.617 回答