Google 电子表格中的时区转换
Posted
技术标签:
【中文标题】Google 电子表格中的时区转换【英文标题】:Timezone conversion in a Google spreadsheet 【发布时间】:2016-04-29 01:26:04 【问题描述】:我知道这看起来很简单。
在 Google 电子表格中,我有一列用于输入一个时区 (GMT) 的时间 另一列应自动获取另一个时区(太平洋时间)的时间
GMT | PT
----------|------------
5:00 AM | 9:00 PM
目前我正在使用
=$C$3-time(8,0,0)
这里的问题是,我想更改夏令时的时间公式。
是否有任何函数或脚本可以自动将夏令时纳入计算。
【问题讨论】:
【参考方案1】:简答
没有内置函数,但您可以构建自定义函数。
示例
/**
* Converts a datetime string to a datetime string in a targe timezone.
*
*@param "October 29, 2016 1:00 PM CDT" datetimeString Date, time and timezone.
*@param "Timezone" timeZone Target timezone
*@param "YYYY-MM-dd hh:mm a z" Datetime format
*@customfunction
*/
function formatDate(datetimeString,timeZone,format)
var moment = new Date(datetimeString);
if(moment instanceof Date && !isNaN(moment))
return Utilities.formatDate(moment, timeZone, format)
else
throw 'datetimeString can not be parsed as a javascript Date object'
注意:
Google Apps 脚本中的new Date(string)
/ Date.parse(string)
实现不支持某些时区缩写。
来自https://tc39.es/ecma262/#sec-date-time-string-format
没有国际标准指定民用时区的缩写,如 CET、EST 等,有时甚至两个非常不同的时区使用相同的缩写。
相关
Get UTC offset from timezone abbreviations说明
为了考虑夏令时区,要转换的值的输入参数应该包括日期,而不仅仅是一天中的时间。您可以设置默认日期和时区来构建 datetimeString,方法是在调用公式之前将其连接起来。
=formatDate("October 29, 2016 "&A2&" GMT","PDT","hh:mm a")
对于目标时区,除了三个字母缩写我们可以使用TZ database names,如America/Los_Angeles
,例如:
=formatDate("October 29, 2016 "&A2&" GMT","America/Los_Angeles","HH:mm")
如果时区缩写和 TZ 名称对于 datetimeString 使用时间偏移(即 UTC-4)失败。
另见
Calculating year, month, days between dates in google apps script参考文献
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date【讨论】:
我发现我需要 RTFM,而且我输入的数据格式有点不正确,这让整个事情都搞砸了 嗨@Rubén。感谢伟大的功能。我遇到了一个我无法解决的问题,希望您能提供帮助。我在澳大利亚,我们的时区在一年中的不同时间更改为 DST。所以我正在尝试使用像澳大利亚/悉尼这样的时区格式。问题是,它在输出中有效(正如您在更新中提到的那样),但在输入中无效。我尝试了许多不同的版本,但都没有运气。你有什么建议吗?另一个奇怪的事情是输入似乎需要一些时区(如 GMT 和 UTC),而不是其他时区(如 AEST 或 AET)。谢谢! 对不起 - 我想我应该举一些例子。 EG 这行得通:=converttz("2020 年 10 月 9 日上午 11:00 PDT","Australia/Sydney","dd/MM/YYYY hh:mm:ss a") 但这不行:=converttz("October 2020 年 9 月 11:00 AM AET","Australia/Sydney","dd/MM/YYYY hh:mm:ss a") 也没有:=converttz("2020 年 10 月 9 日 11:00 AM 澳大利亚/布里斯班", "澳大利亚/悉尼","dd/MM/YYYY hh:mm:ss a") @Luke 我更新了我的答案:tl;dr:Google Apps 脚本并不支持所有时区缩写/名称。 非常感谢@Rubén 的更新。多可惜!我喜欢你的脚本的简单性,但由于我处理的是澳大利亚时区,看起来我将不得不使用 moment.js 实现 Ryan 的解决方案。希望这会帮助许多其他人。为了增加您的澄清,对于其他人来说 - 其他时区似乎适合输出。只是输入受到限制。【参考方案2】:本教程非常有用:https://davidkeen.com/blog/2017/01/time-zone-conversion-in-google-sheets/
Google 表格没有内置的时区数据转换方式,但通过使用 Moment.js 和 Google 脚本编辑器的强大功能,我们可以将时区功能添加到任何表格中。
这些是我复制到脚本项目中的文件:
https://momentjs.com/downloads/moment-with-locales.js另存为moment.js https://momentjs.com/downloads/moment-timezone-with-data.js 保存为 moment-timezone.js确保首先添加 moment.js 脚本并将其置于 moment-timezone.js 脚本之上,因为 moment-timezone.js 依赖于它。
然后在你的 other 脚本项目中,你的 Code.gs 文件可以如下所示:
var DT_FORMAT = 'YYYY-MM-DD HH:mm:ss';
/**
https://***.com/questions/34946815/timezone-conversion-in-a-google-spreadsheet/40324587
*/
function toUtc(dateTime, timeZone)
var from = m.moment.tz(dateTime, DT_FORMAT, timeZone);//https://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/
return from.utc().format(DT_FORMAT);
/**
https://***.com/questions/34946815/timezone-conversion-in-a-google-spreadsheet/40324587
*/
function fromUtc(dateTime, timeZone)
var from = m.moment.utc(dateTime, DT_FORMAT);//https://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/
return from.tz(timeZone).format(DT_FORMAT);
【讨论】:
虽然 moment.js 在其他情况下可以节省大量编程,但对于这种特定情况,内置的Utilities.formatDate(...)
做得很好。你不觉得吗?
@Rubén 我从不想考虑是使用 PST 还是 PDT。如果我已经指定了日期,那感觉是多余且容易出错的。我宁愿只为太平洋时间指定 PT 或“America/Los_Angeles”并让系统处理它。
在一个“国际项目”上(我在墨西哥,我的客户在西班牙)我最近将 GMT+1 更改为欧洲/马德里,它工作正常,所以我认为它也应该工作美国/洛杉矶
@Rubén 然后我需要根据一年中的时间管理从 UTC 增加或减少多少小时。这是同样的问题。
对不起,我没有不关注你。为什么你需要管理在这个问题的上下文中添加/减去多少小时?【参考方案3】:
当我找到此页面时,我遇到了同样的问题(将马尼拉时间转换为悉尼时间并自动调整夏令时)。
我不想拥有自定义函数,但我发现在悉尼,AEST(澳大利亚东部标准时间)从 4 月的第一个星期日开始,而 AEDT(澳大利亚东部夏令时间)从 10 月的第一个星期日开始.
所以我想,如果我能找到一个公式来检测日期是否介于 4 月的第一个星期日和 10 月的第一个星期日(标准时间)之间,那么我可以自动将 1 小时添加到马尼拉时间的通常 2 小时夏令时(两个日期之外的日期)有悉尼时间。
这两种 Excel 解决方案在 Google 表格中运行良好:
How You Can Determine the First Sunday in a Month in Excel How to determine if a date falls between two dates or on weekend in Excel今年四月的第一个星期日(A1):
=CONCATENATE("4/1/",Year(today()))+CHOOSE(WEEKDAY(CONCATENATE("4/1/",Year(today())),1),7,6,5,4,3,2,1)
今年 10 月的第一个星期日 (A2):
=CONCATENATE("10/1/",year(today()))+CHOOSE(WEEKDAY(CONCATENATE("10/1/",year(today())),1),7,6,5,4,3,2,1)
DST 检测器 (A3) — 如果某个日期不在这两个日期范围内,则它是悉尼的 DST:
=IF(AND(today()>A1,today()<A2),"AEST","AEDT")
悉尼时间(A4):
=NOW()+TIME(IF(A3="AEDT",3,2),0,0)
NOW()
可以更改为任何时间格式进行制表:
【讨论】:
欢迎来到Stack Overflow。我很好奇你为什么不想使用自定义功能。这是关于对电子表格性能影响的担忧吗?您能否简要分享一个使用案例,您发现使用您的解决方案比使用自定义函数更好? @Rubén 这与电子表格性能无关。只是我对编程还不熟悉,所以我觉得在尝试自定义函数之前我会先尝试其他解决方案。如果我需要转换许多时区,我相信使用您的自定义函数会更有效。 ;)【参考方案4】:我是新贡献者和新手,但我偶然发现了一个功能,尽管在表格/时区问题上搜索了很多小时,但仍未提及。希望这个相对简单的解决方案会有所帮助。
对于我的工作表,我只想添加一行并在前两个单元格中自动填充本地工作表日期和时间。
.getTimezoneOffset() 返回客户端 TZ 和 GMT 之间的分钟差,在夏令时期间在纽约是 240。该函数返回带有“GMT-x”的区域的正数,反之亦然带有“GMT+x”的区域。因此需要除以 -60 才能得到正确的时间和符号。
function addRow()
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
sheet.insertRows(2, 1);
rightNow = new Date();
var tzOffset = "GMT" + rightNow.getTimezoneOffset() / -60;
var fDate = Utilities.formatDate(rightNow, tzOffset, "MM-dd-yyyy");
var fTime = Utilities.formatDate(rightNow, tzOffset, "HH:mm");
sheet.getRange('A2').setValue(fDate);
sheet.getRange('B2').setValue(fTime);
sheet.getRange('C2').setValue(tzOffset);
我发现我不是第一个回应提到 .getTimezoneOffset() 的 GMT 校正难题的人。然而,这个帖子对这个话题的看法最多,所以我认为这个选项值得一提。
DST 于 2021 年 11 月 7 日在这里结束,所以如果它没有按预期调整到“GMT-5”,我会报告回来
.getTimezoneOffset()
【讨论】:
【参考方案5】:只需使用 TZData 格式从 UTC“拉取”同步并显示您的选择。
为了将您的单元格显示“更改”为柏林当地时间的示例
=fromUTC(N82, "Europe/Berlin")
或东京
=fromUTC(N82, "Asia/Tokyo")
或旧金山
=fromUTC(N82, "America/Inuvik")
时区参考点在这里 >>
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
【讨论】:
【参考方案6】:这也可以在没有宏的情况下完成。只需使用函数和数据操作就足够了。在这里解释整个过程会有点麻烦。只需研究各种时间函数的工作原理并发挥您的创造力即可。
提示:如果您需要当前日期和时间,请使用=NOW()
。如果您需要找出不同日期之间的精确时间差异,您实际上需要它。
当您只需要时间时使用=NOW()-INT(NOW())
(如果两个时间都在同一日期,则日期会被截断)。然后将相应的单元格或单元格格式化为时间(即4:30 PM
),而不是日期时间(3/25/2019 17:00:00
)。后者是您想要同时显示日期和时间时使用的格式......就像您使用 NOW()
时一样。
还可以在线搜索各种标准时区(PT、MT、CT、ET、AT)相对于协调世界时 (UTC) 的夏令时偏移量。例如,在 2019 年,太平洋时间的偏移量为 UTC-7,此时从 3 月 10 日凌晨 2 点(太平洋)开始观察到 DST,直到 11 月 3 日凌晨 2 点。这意味着从 UTC 到太平洋的时间差是 7 小时。其余时间为 8 小时 (UTC-8)。在 3 月某个时间(今年 10 日)开始的 DST 遵守期间,它通过将时钟向前移动 1 小时或我们所知的 UTC-7(即夏令时)从 PST 变为 PDT。在 DST 遵守之后,它通过将时钟再次向后移动 1 小时,或我们所知的 UTC-8(或冬季时间)从 PDT 变为 PST。请记住,时钟在三月提前一小时,以便更好地利用时间。这就是我们所说的 DST,即夏令时。因此,在 3 月 8 日凌晨 2 点之后(今年是 2019 年),我们进入了 UTC-7。在 11 月,我们做相反的事情。 11 月 3 日凌晨 2 点,随着冬天的到来,时钟拨回一小时。那时我们又回到了标准时间。看起来有点混乱,其实不然。
因此,基本上,对于 PT 的人来说,他们在 3 月从 PST 到 PDT,在 11 月从 PDT 到 PST。山地时间、中部时间和东部时间的过程完全相同。但它们有不同的 UTC 时间偏移。 MT 是 UTC-6 或 UTC-7。 CT 是 UTC-5 或 UTC-6。 ET 是 UTC-4 或 UTC-5。这一切都取决于我们是在夏时制,以便更好地利用日光和工作时间,还是在冬时(AKA,标准时间)。
彻底研究这些并了解它们的工作原理,并使用 Excel 或 Google 表格中的各种时间函数,如 TIME(#,#,#)
和 NOW()
函数等,相信我,很快你就能做到无需使用 VBA Google Apps 脚本即可使用简单功能的专业人士。不过,您也可以使用TEXT()
函数,使用=TEXT(L4,"DDD, MMM D")&" | "&TEXT(L4,"h:mm AM/PM")
之类的技巧,其中L4 包含您的日期时间戳,以显示时间和日期格式。 VALUE()
函数也时不时派上用场。您甚至可以在不使用宏的情况下设计一个数字倒数计时器。为此,您需要在电子表格设置中创建一个循环引用并将迭代次数设置为 1,并将时间显示设置为每 1 分钟一次。
官方 timeanddate dot com 网站是一个很好的信息来源,让所有人了解时区以及如何处理日光时间。他们那里也有所有 UTC 偏移量。
【讨论】:
“彻底研究这些”?不是一个好主意。时区几乎和密码学一样棘手。始终依赖经过良好测试的库。 我认为 - 硬编码不是要走的路。当欧盟废除夏令时会发生什么?欧盟和美国都在 3 月更换时钟,但不像过去那样在同一天更换时钟 - 相隔数周。 这个问题是关于 Google 表格,而不是 Excel,所以我做了一点修正。 我不赞成编写自己的时区库。时区是混乱的,并且会随着立法的突发奇想而改变。因此,除非您想承诺从现在开始跟踪夏令时规则的所有最新更改,否则您应该使用库! 我发现存储数据时最好坚持 GMT/UTC,然后根据需要进行转换【参考方案7】:在 Google 表格中创建您自己的时区转换器:
第 1 步: Create your table for the timezone converter.
第 2 步: Enter the times for your time zones in a column. 注意:确保选择日期/时间格式(选择单元格 -> 格式 -> 数字 -> 时间/日期)
第 3 步: 使用以下函数编写转换时区的公式 Google Sheet Functions
=HOUR(A8)+(B3*C3) converts the hours.
=MINUTE(A8)+(B3*C3) converts the minutes.
第 4 步:使用 TIME(h,m,s) 函数转换回时间格式
=TIME(HOUR(A8)+(B3*C3), MINUTE(A8)+(B3*C3), SECOND(A8))
这是一种转换时区的简单方法。 但是,如果您想实现一个准确的时区转换器,可以处理前一天、第二天以及超过 24 小时、超过 60 分钟的时间,请使用 MOD 操作并处理所有情况。 访问(或使用)此谷歌表以供参考: https://docs.google.com/spreadsheets/d/1tfz5AtU3pddb46PG93HFlzpE8zqy421N0MKxHBCSqpo/edit?usp=sharing
【讨论】:
以上是关于Google 电子表格中的时区转换的主要内容,如果未能解决你的问题,请参考以下文章
如何获取 Google 电子表格时区偏移字符串而不是时区字符串?
Google 电子表格 ArrayFormula + VLookup 转换
如何将 Google 电子表格的工作表字符串 id 转换为整数索引 (GID)?