Google 表格单元格中的 ISO-8601 日期字符串

问题描述 投票:0回答:7

我的工作表的一列中有一堆 ISO-8601 格式的字符串。 如何让谷歌表格将它们视为日期,以便我可以对它们进行数学运算(例如,两个单元格之间的分钟差)? 我只是尝试了

=Date("2015-05-27T01:15:00.000Z")
,但没有乐趣。 必须有一种简单的方法来做到这一点。 有什么建议吗?

datetime google-sheets google-sheets-formula iso8601
7个回答
184
投票

要获取实际的日期值,您可以使用正常的数字格式对其进行格式化...

=DATEVALUE(MID(A1,1,10)) + TIMEVALUE(MID(A1,12,8))

例如。

A B
1 2016-02-22T05:03:21Z 2016 年 2 月 22 日 5:03:21 上午
  • 假设时间戳采用 UTC 格式
  • 忽略毫秒(尽管您可以轻松添加)

DATEVALUE()
函数将格式化的日期字符串转换为值,
TIMEVALUE()
对时间执行相同的操作。在大多数电子表格中,日期和时间都用数字表示,其中整数部分是自 1900 年 1 月 1 日以来的天数,小数部分是当天的时间分数。例如,2009 年 6 月 11 日 17:30 约为 39975.72917。

上面的公式将日期部分和时间部分分别解析,然后将它们相加。


45
投票

我发现使用起来更简单

=SUM(SPLIT(A2,"TZ"))

格式化

yyyy-MM-dd HH:mm:ss.000
即可再次看到日期值为 ISO-8601。


16
投票

试试这个

=CONCATENATE(TEXT(INDEX(SPLIT(SUBSTITUTE(A1,"Z",""),"T"),1),"yyyy-mm-dd")," ",TEXT(INDEX(SPLIT(SUBSTITUTE(A1,"Z",""),"T"),2),"hh:mm:ss"))

其中 A1 可以是带有 ISO-8601 格式字符串的单元格或字符串本身。


8
投票

打开 Apps 脚本并将此自定义函数粘贴到编辑器中。

function isoDate(isoDateString) {
  return new Date(isoDateString)
}

将其与如下公式一起使用:

=isoDate("2023-01-06T22:37:12Z")

结果将在表格中显示为日期。


0
投票

我发现使用正则表达式替换是一种更简单、干净且可读的方法:

=regexreplace(A1, "T|Z", " ") + B1
A B C D
1 2023-04-17T16:29:20.085Z -3:00:00 1080805:29:20 2023年4月17日13:29:20
  • A1
    是要格式化的值;
  • B1
    是您所在地区的时区差异;
  • C1
    有公式且无格式;
  • D1
    具有相同的公式,格式为
    Date Time

正则表达式用空格替换字母 T 和 Z。

+ B1
部分将添加时差以获得您所在时区的最终值。

如果您愿意,您可以在公式中对其进行硬编码,而不是使用单元格。

=regexreplace(A1, "T|Z", " ") + "-3:00"

或者,如果您不想在公式中得到这种差异,您可以删除

+ B1
部分

=regexreplace(A1, "T|Z", " ")

0
投票

这是一个简单的版本,它将 T 替换为空格,然后采用前 19 个字符来排除毫秒和尾随 Z,最后使用 -- 将其强制转换为正确的日期/时间值。

确保将该列转换为日期/时间而不是数字或类似内容,以便正确显示:)

=--LEFT(SUBSTITUTE(A1,"T"," "),19)

-1
投票

我使用以下 Apps 脚本函数将 ISO8601 时间戳转换为相应电子表格时区中的串行日期时间:

/** JS Date to Excel DateTime (AKA SERIAL_NUMBER date).
 *
 * @param date A JavaScript date object, possibly representing a datetime like 2022-11-11T15:24:00.000Z..
 * @param timeZoneOffsetMillies The time zone offset of the target serial date time (usually the one of the sheet).
 *
 * @return A Excel serial date like 44876.641666666605.
 */
const dateToSerialDateTime = function(date, timeZoneOffsetMillies) {
    /** Milliseconds per day (24 * 60 * 60 * 1000). */
    const MILLISECONDS_PER_DAY = 86400000;
    const timeZoneOffsetDays = timeZoneOffsetMillies / MILLISECONDS_PER_DAY;
    return ((date.getTime() / MILLISECONDS_PER_DAY) + 25569) + timeZoneOffsetDays; // 1970-01-01 - 1900-01-01 = 25569
};


/** Get the the timezone offset in milliseconds.
 *
 * @param timeZone The time zone in text format, ie. "Europe/Paris"
 * @return {number} Time zone offset in milliseconds.
 */
const getTimeZoneOffset = function(timeZone) {
    const strOffset = Utilities.formatDate(new Date(), timeZone, "Z");
    const offsetSeconds = ((+(strOffset.substring(0, 3))) * 3600) + ((+strOffset.substring(3)) * 60);
    return offsetSeconds * 1000;
}


/**
 * Returns the current sheets timezone.
 *
 * @return The current sheets timezone in IANA time zone database name format (ie Europe/Berlin).
 * @customfunction
 */
function TIMEZONE() {
    return SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone();
}


/**
 * Returns the current sheets timezone offset in milliseconds.
 *
 * @return The current sheets timezone offset in milliseconds.
 * @customfunction
 */
function TIMEZONE_OFFSET() {

    const tz = TIMEZONE();
    return tz != null ? getTimeZoneOffset(tz) : null;
}


/**
 * Convert ISO8601 timestamp strings (ie. 2022-11-22T14:47:01+0100) to a Sheets serial datetime.
 *
 * @param {string|Array<Array<string>>} input Input ISO8601 date string to parse.
 *
 * @return {number} The native sheets "serial datetime" as double (format the field as Number->Date Time manually).
 * @customfunction
 */
function PARSE_ISO8601(input) {

    const tzOffsetMillies = TIMEZONE_OFFSET();
    const parseIso8601 = ts => ts ? dateToSerialDateTime(new Date(ts), tzOffsetMillies) : null;

    return Array.isArray(input) ? input.map(row => row.map(field => parseIso8601(field))) : parseIso8601(input);
}

© www.soinside.com 2019 - 2024. All rights reserved.