假设您网站的用户输入一个日期范围。
2009-1-1 to 2009-1-3
您需要将此日期发送到服务器进行某些处理,但服务器希望所有日期和时间均采用 UTC 格式。
现在假设用户在阿拉斯加。 由于它们位于与 UTC 完全不同的时区,因此需要将日期范围转换为如下所示:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
使用 JavaScript Date
对象,如何将第一个“本地化”日期范围转换为服务器会明白吗?
Suppose a user of your website enters a date range.
2009-1-1 to 2009-1-3
You need to send this date to a server for some processing, but the server expects all dates and times to be in UTC.
Now suppose the user is in Alaska. Since they are in a timezone quite different from UTC, the date range needs to be converted to something like this:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
Using the JavaScript Date
object, how would you convert the first "localized" date range into something the server will understand?
发布评论
评论(30)
您可以使用以下方法将任何js日期转换为UTC:
You can use the following method to convert any js date to UTC:
简单又愚蠢
Simple and stupid
来源:MDN 网络文档
格式您需要使用
.toISOString()
方法创建。 对于旧版浏览器(ie8 及以下),本身不支持此方法,可以在 此处:这将使您能够执行您需要的操作:
对于时区工作,moment.js 和 moment.js timezone 确实是非常宝贵的工具......特别是对于在客户端和客户端之间导航时区而言服务器 JavaScript。
Source: MDN web docs
The format you need is created with the
.toISOString()
method. For older browsers (ie8 and under), which don't natively support this method, the shim can be found here:This will give you the ability to do what you need:
For Timezone work, moment.js and moment.js timezone are really invaluable tools...especially for navigating timezones between client and server javascript.
这是我的方法:
生成的 utc 对象并不是真正的 UTC 日期,而是经过转换以匹配 UTC 时间的本地日期(请参阅注释)。 然而,在实践中它确实起到了作用。
更新:这个答案是在调用
utc.toString()
,utc.toLocaleString()
等。 不过,有更好的解决方案,特别是现在使用现代浏览器,我应该研究改进的答案。 基本上,now.toISOString()< /code>
(IE 9+) 是您想要使用的。
Here's my method:
The resulting
utc
object isn't really a UTC date, but a local date shifted to match the UTC time (see comments). However, in practice it does the job.Update: This answer is a quick-and-dirty way to get the UTC date when calling
utc.toString()
,utc.toLocaleString()
, etc. Though, there are better solutions, in particular nowadays with modern browsers, and I should work on an improved answer. Basically,now.toISOString()
(IE 9+) is what you want to use.转换为 ISO 而不更改日期/时间
转换为 ISO 并更改日期/时间(日期/时间将更改)
小提琴链接
Convert to ISO without changing date/time
Convert to ISO with change in date/time(date/time will be changed)
Fiddle link
转换为 UTC 并将其保留为日期对象的另一种解决方案:
(它的工作原理是从格式化字符串末尾删除“GMT”部分,然后将其放回 Date 构造函数)
我需要这样做才能与日期时间选择器库交互。 但一般来说,以这种方式处理日期是一个坏主意。
用户通常希望使用本地时间的日期时间,因此您可以更新服务器端代码以正确解析带有偏移量的日期时间字符串,然后转换为 UTC(最佳选择),或者在发送到客户端之前转换为 UTC 字符串客户端。服务器(如威尔·斯特恩的回答)
Another solution to convert to UTC and keep it as a date object:
(It works by removing the ' GMT' part from the end of the formatted string, then putting it back into the Date constructor)
I needed to do this to interface with a datetime picker library. But in general it's a bad idea to work with dates this way.
Users generally want to work with datetimes in their local time, so you either update the server side code to parse datetime strings with offsets correctly, then convert to UTC (best option) or you convert to a UTC string client-side before sending to the server (like in Will Stern's answer)
无论客户端设置什么时区,我的解决方案都会保持日期相同。 也许有人会发现它很有用。
我的用例:
我正在创建一个待办事项应用程序,您可以在其中设置任务日期。 无论您位于哪个时区,此日期都应保持不变。
示例。 您想在 6 月 25 日上午 8 点给您的朋友打电话。
您在 5 天前(6 月 20 日)在中国时创建了此任务。
然后,在同一天,您飞往纽约几天。
然后在 6 月 25 日,当你还在纽约时,你早上 7:30 起床(这意味着你应该在 30 分钟内收到任务通知(即使在你创建任务时所在的中国已经是下午 1:30)任务)
我所在的任何时区的早上 8 点执行”。
所以该任务忽略时区。这意味着“我想在 。
它的意思是 - 当用户选择她/他的时区中的某个日期时 - 我将这个日期转换为 UTC 日期,即您选择中国的上午 8 点,但我将其转换为 UTC 的上午 8
点 下次您打开应用程序时 - 我读取以 UTC 保存的日期并将其转换为您当前时区的相同日期 - 例如,我将 UTC 上午 8 点转换为纽约时区上午 8 点
此解决方案意味着该日期可以。 取决于您设置它时的位置以及您正在阅读它的位置,但它保持不变,让您“感觉”总是在同一时区:
含义
首先 - 我们有。忽略时区从/到 UTC 转换的 2 个主要函数:
然后,我保存/读取此日期,如下所示:
My solution keeps the date the same no matter what timezone is set on the client-side. Maybe someone will find it useful.
My use case:
I'm creating a todo app, where you set date of your task. This date should remain constant no matter what timezone you're in.
Example. You want to call your friend at 8 am on June 25th.
You create this task 5 days before (June 20th) while you're in China.
Then, on the same day, you fly to New York for a few days.
Then on June 25th, while you're still in New York, you wake up at 7:30 am (which means you should receive task notification in 30 mins (even tho it's 1:30 pm already in China where you were when creating the task)
So the task is ignoring the timezone. It means 'I want to do it at 8 am in whatever timezone I'll be in'.
What I do is let's say 'I assume you're always in London Timezone - UTC'.
What it means is - when the user picks some date in her/his Timezone - I convert this date to the same date in UTC. ie. You pick 8 am in China, but I convert it to 8 am in UTC.
Then - next time you open the app - I read the date saved in UTC and convert it to the same date in your current timezone - eg. I convert 8 am in UTC to 8 am in the New York timezone.
This solution means that the date can mean something else depending on where you are when setting it and where you're reading it, but it remains constant in a way that it 'feels' like you're always in the same timezone.
Let's write some code:
First - we have 2 main functions for converting from/to UTC ignoring timezone:
Then, I save/read this date like:
浏览器可能有所不同,您还应该记住不要信任客户端生成的任何信息,也就是说,以下语句对我有效(Mac OS X 10.8.2 上的 Google Chrome v24)
var utcDate = new Date( new Date().getTime());
编辑:“这与
new Date()
有什么不同?” 请参阅此处: https://developer.mozilla.org/ en-US/docs/Web/JavaScript/Reference/Global_Objects/Date按照前面的答案所述添加 60000 * Date.getTimezoneOffset() 是不正确的。 首先,出于显示目的,您必须将所有日期/时间视为带有时区修饰符的 UTC。
同样,浏览器可能有所不同,但是 Date.getTime() 返回自 1970-01-01 UTC/GMT 以来的毫秒数。 如果您像上面那样使用此数字创建新日期,则它将是 UTC/GMT。 但是,如果您通过调用 .toString() 显示它,它将显示为您的本地时区,因为 .toString() 使用您的本地时区,而不是调用它的 Date 对象的时区。
我还发现,如果您在某个日期上调用 .getTimezoneOffset() ,它将返回您的本地时区,而不是您调用它的日期对象的时区(但是我无法验证这是标准的)。
在我的浏览器中,添加 60000 * Date.getTimezoneOffset() 创建一个不是 UTC 的 DateTime。 但是,当在我的浏览器中显示时(例如: .toString() ),它会在我的本地时区中显示 DateTime,如果忽略时区信息,该日期时间将是正确的 UTC 时间。
Browsers may differ, and you should also remember to not trust any info generated by the client, that being said, the below statement works for me (Google Chrome v24 on Mac OS X 10.8.2)
var utcDate = new Date(new Date().getTime());
edit: "How is this different than just
new Date()
?" see here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateAdding the 60000 * Date.getTimezoneOffset() as previous answers have stated is incorrect. First, you must think of all Dates/Times as already being UTC with a timezone modifier for display purposes.
Again, browsers may differ, however, Date.getTime() returns the number of milliseconds since 1970-01-01 UTC/GMT. If you create a new Date using this number as I do above, it will be UTC/GMT. However, if you display it by calling .toString() it will appear to be in your local timezone because .toString() uses your local timezone, not the timezone of the Date object it is called on.
I have also found that if you call .getTimezoneOffset() on a date, it will return your local timezone, not the timezone of the date object you called it on (I can't verify this to be standard however).
In my browser, adding 60000 * Date.getTimezoneOffset() creates a DateTime that is not UTC. However when displayed within my browser (ex: .toString() ), it displays a DateTime in my local timezone that would be correct UTC time if timezone info is ignored.
应该可以在大多数较新的浏览器中工作。 它在 Firefox 6.0 上返回
2012-07-28T00:00:00.000Z
ought to work in most newer browsers. it returns
2012-07-28T00:00:00.000Z
on Firefox 6.0您是否想将日期转换为这样的字符串?
我将创建一个函数来执行此操作,并将其添加到 Date 原型中,尽管这有点争议。 如果您不习惯这样做,那么您可以将其作为独立函数,将日期作为参数传递。
如果您需要 UTC 时间,只需将所有 get* 函数替换为 getUTC*,例如:getUTCFullYear、getUTCMonth、getUTCHours...,然后在末尾添加“+00:00”而不是用户的时区偏移量。
Are you trying to convert the date into a string like that?
I'd make a function to do that, and, though it's slightly controversial, add it to the Date prototype. If you're not comfortable with doing that, then you can put it as a standalone function, passing the date as a parameter.
If you needed it in UTC time, just replace all the get* functions with getUTC*, eg: getUTCFullYear, getUTCMonth, getUTCHours... and then just add "+00:00" at the end instead of the user's timezone offset.
在处理日期时,我的建议是将日期解析为用户输入中的各个字段。 你可以把它当作一个完整的字符串来使用,但你这是在玩火。
JavaScript 可以以不同的方式处理不同格式的两个相同日期。
https://developer.mozilla.org/en -US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
切勿执行以下操作:
将用户输入的日期解析为各个字段后,创建一个日期对象。 创建日期对象后,通过添加时区偏移将其转换为 UTC。 我无法强调使用 DST 导致的日期对象的偏移量有多么重要(但这是另一个讨论来说明原因)。
现在您可以将 UTC 时间的日期传递给服务器。 我再次强烈建议不要使用任何日期字符串。 要么将其传递到服务器,分解为您需要的最低粒度,例如年、月、日、分钟,或者作为 unix 纪元中的毫秒之类的值。
My recommendation when working with dates is to parse the date into individual fields from user input. You can use it as a full string, but you are playing with fire.
JavaScript can treat two equal dates in different formats differently.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
Never do anything like:
Once you have your date parsed into its individual fields from user input, create a date object. Once the date object is created convert it to UTC by adding the time zone offset. I can't stress how important it is to use the offset from the date object due to DST (that's another discussion however to show why).
Now you can pass the date to the server in UTC time. Again I would highly recommend against using any date strings. Either pass it to the server broken down to the lowest granularity you need e.g. year, month, day, minute or as a value like milliseconds from the unix epoch.
如果您经常处理日期,那么值得使用 moment.js (http://momentjs.com)。 转换为 UTC 的方法是:
您可以使用 format 将日期更改为您想要的任何格式:
moment 中也有偏移选项,但还有一个用于处理时区的附加补充库(http://momentjs.com/timezone/)。 时间转换就像这样简单:
If you are dealing with dates a lot, it's worth using moment.js (http://momentjs.com). The method to convert to UTC would be:
You can use format to change your date to any format you want:
There is offset options in moment as well but there is an additional complementary library for dealing with timezone (http://momentjs.com/timezone/). The time conversion would be as simple as this:
我发现 jQuery 全球化插件 日期解析效果最好。 其他方法存在跨浏览器问题,并且像 date.js 这样的东西已经有一段时间没有更新了。
您也不需要页面上有 datePicker。 您可以调用类似于文档中给出的示例的内容:
I've found the jQuery Globalization Plugin date parsing to work best. Other methods had cross-browser issues and stuff like date.js had not been updated in quite a while.
You also don't need a datePicker on the page. You can just call something similar to the example given in the docs:
对于其他人的目标是将其作为“日期对象”而不是字符串,并且您只想显示没有 TZ 的日期/时间(可能是硬编码),您可以做的是:
然后您可以做一些事情例如:
我们将在 ${format(tomorrowUTC, 'EEEE do MMMM hh:mmaaa')} UTC
删除您的帐户(
format
是 date-fns 函数,如果需要,可以使用其他库);这有点“hacky”,因为它仍然使用您当地的时区,但如果您只想显示日期而不是时区,那么这可以工作。
For other people whos goal is to get it as a "Date Object" and not as a string, and you only want to display the date/time without the TZ (probably hardcoded), what you can do is:
You can then do stuff like:
We will delete your account at ${format(tomorrowUTC, 'EEEE do MMMM hh:mmaaa')} UTC
(
format
is a date-fns function, you can use other lib if you want);This is kinda "hacky" as this is still using your local timezone, but if you just wanna display the date and not the timezone, then this works.
我刚刚发现 Steven Levithan 的 date.format.js 的 1.2.3 版本正是我想要的。 它允许您为 JavaScript 日期提供格式字符串,并将从本地时间转换为 UTC。 这是我现在使用的代码:
I just discovered that the 1.2.3 version of Steven Levithan's date.format.js does just what I want. It allows you to supply a format string for a JavaScript date and will convert from local time to UTC. Here's the code I'm using now:
来源:MDN 网络文档
这意味着如果本地时区晚于 UTC,则偏移量为正;如果早于 UTC,则偏移量为负。 例如,对于时区 UTC+02:00,将返回 -120。
注意:这会将日期对象时间转换为UTC±00:00,并且不转换其时区,因此日期对象时区仍将相同,但值将以 UTC±00:00 为单位。
Source: MDN web docs
This means that the offset is positive if the local timezone is behind UTC, and negative if it is ahead. For example, for time zone UTC+02:00, -120 will be returned.
NOTE: This will shift the date object time to UTC±00:00 and not convert its timezone so the date object timezone will still the same but the value will be in UTC±00:00.
这将为您提供正确的 UTC 日期和时间。
这是因为
getTimezoneOffset()
将为您提供以分钟为单位的时区差异。我建议您不要使用
toISOString()
因为输出将在字符串中因此将来您将无法操作日期This will give you the proper UTC Date and Time.
It's because the
getTimezoneOffset()
will give you the timezone difference in minutes.I recommend you that not to use
toISOString()
because the output will be in the string Hence in future you will not able to manipulate the date此方法将为您提供:
2017-08-04T11:15:00.000+04:30
,您可以忽略zone变量以简单地获取2017-08-04T11 :15:00.000
。This method will give you :
2017-08-04T11:15:00.000+04:30
and you can ignore zone variable to simply get2017-08-04T11:15:00.000
.使用 moment.js UTC 方法;
Using moment.js UTC method;
如果您需要日期对象
仅传递日期字符串 Date 假定时间为 00:00 按时区移动:
如果添加当前小时和分钟,您将获得正确的日期:
If you need Date Object
Passing only date string Date assumes time to be 00:00 shifted by time zone:
If you add current hours and minutes you get proper date:
这个功能对我来说效果很好。
This function works beautifully for me.
这就是我过去所做的:
This is what I have done in the past:
如果您的日期有时区,您可以使用 date-fns-tz :
If your date has the timezone on it you can use date-fns-tz:
查看您的问题,很明显您只想将日期范围发送到后端以进行进一步的后处理。
我假设您遵守标准数据指南,该指南期望数据采用特定格式。 例如,我使用 ODATA,它是一个 RESTfull API,它期望日期时间对象采用以下格式:-
这可以通过下面发布的代码片段轻松实现(请根据您的要求更改格式)。
var mydate;//假设这是我想要公开的日期对象
var UTCDateStr = mydate.getUTCFullYear() + "-" + mydate.getUTCMonth() + "-" + mydate.getUTCDate() + "T00:00:00";
另一方面,如果您处于我的情况是,您从后端收到了日期,浏览器会将其转换为您的本地日期。 另一方面,您对 UTC 日期感兴趣,那么您可以执行以下操作:-
var mydate;//假设这是我想要公开的日期对象
var UTCDate = new Date(mydate);/*创建日期对象的副本。 仅当您出于某种原因需要原始本地日期时才需要*/
UTCDate.setTime(UTCDate.getTime() + UTCDate.getTimezoneOffset() * 60 * 1000);
上面的代码片段基本上是根据时区添加/减去浏览器添加/减去的时间。
例如,如果我处于 EST(GMT-5) 并且我的服务返回日期时间对象 = Wed Aug 17 2016 00:00:00 GMT-0500
我的浏览器自动减去时区偏移(5小时)来获取我的当地时间。 因此,如果我尝试获取时间,我会得到 Wed Aug 16 2016 19:00:00 GMT-0500。 这会导致很多问题。 有很多库肯定会让这变得更容易,但我想分享纯 JS 方法。
欲了解更多信息,请查看:http://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/ 我在哪里得到了我的灵感。
希望这可以帮助!
Looking at your question its clear that you just want to send the date range to your backend for further post processing.
I am assuming you are conforming to the standard data guidelines which expect the data to be in a particular format. For example, I use ODATA which is a RESTfull API which expects date time objects to be in the format:-
That can be easily achieved via the snippet posted below(Please change the format as per your requirement).
var mydate;//assuming this is my date object which I want to expose
var UTCDateStr = mydate.getUTCFullYear() + "-" + mydate.getUTCMonth() + "-" + mydate.getUTCDate() + "T00:00:00";
If on the other hand, you are in my situation wherein you have received a date from your backend, and the browser converts that to your local date. You on the other hand are interested in the UTC date then you can perform the following:-
var mydate;//assuming this is my date object which I want to expose
var UTCDate = new Date(mydate);/*create a copy of your date object. Only needed if you for some reason need the original local date*/
UTCDate.setTime(UTCDate.getTime() + UTCDate.getTimezoneOffset() * 60 * 1000);
The code snippet above basically adds/subtracts the time added/subtracted by the browser based on the timezone.
For example if I am in EST(GMT-5) and my Service returns a date time object = Wed Aug 17 2016 00:00:00 GMT-0500
my browser automatically subtracts the timezone offset(5hrs) to get my local time. So if I try to fetch the time I get Wed Aug 16 2016 19:00:00 GMT-0500. This causes a lot of problems. There are a lot of libraries out there which will definitely make this easier but I wanted to share the pure JS approach.
For more info please have a look at: http://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/ where in I got my inspiration.
Hope this helps!
使用 moment 包,您可以轻松地将 UTC 日期字符串转换为新的 Date 对象:
当您的服务器不支持时区并且您希望始终将 UTC 日期存储在服务器中并将其作为新的 Date 对象获取时,这特别有用。 上面的代码满足了我对这个线程所针对的类似问题的要求。 在此分享,以便对其他人有所帮助。 我在任何答案中都没有看到上述解决方案。 谢谢。
Using moment package, you can easily convert a date string of UTC to a new Date object:
This specially helps when your server do not support timezone and you want to store UTC date always in server and get it back as a new Date object. Above code worked for my requirement of similar issue that this thread is for. Sharing here so that it can help others. I do not see exactly above solution in any answer. Thanks.
到目前为止,我发现获取 GMT 时间的最佳方法是首先获取您本地的日期时间。 然后转换为 GMT 字符串。 然后使用该字符串通过删除时区来构建新时间。
注意: - 它将创建 GMT 中的新日期时间。 但这将是本地日期时间,因为时区将附加到它。
By far the best way I found to get the GMT time is first get your local date time. Then convert in to GMT String. Then use the string to build new time by removing the timezone.
Note: - it will create the new datetime in GMT. But it will be local date time as timezone will be attached to it.
我将为这个非常古老的问题添加一个新答案,因为它经常被引用,并且所有其他答案都展示了不正确的方法,例如纪元转换或重新解析,如此处所述。 此外,他们只是解决问题的标题。 我将重点关注问题正文,而忽略标题。
首先,请注意这种格式是非标准的。 月份和日期部分应该使用两位数字。 ISO 8601 兼容性需要前导零,这通常是日期解析器所期望的。 日期应表示为
2009-01-01
到2009-01-03
。下一个错误是设计中的“...所有日期和时间均采用 UTC”。 用户没有选择日期和时间,他们只选择了一个日期。 整个日期无法转换为 UTC,因为它们一开始就不位于任何特定时区。 假设否则类似于我递给您一份纸质日历(如下所示)并询问它所在的时区。
当然,这些日子都没有时区,因为该设备上不显示时间。 每个方块代表给定月份和年份内的特定日期。 如果将时间与每一天联系起来,那么它就不是单个时间,而是从一天开始到一天结束的时间范围。天。 当然,如果日历要由特定时区的人读取,那么每个点都可以转换为 UTC。 但通常我们不会四处传递时间戳范围给彼此。 相反,我们只使用日期 - 所以这也是您的程序应该做的。
这确实是标准 HTML5
标签。 从下面选择一个日期,并注意给定的
value
是 ISO 8601yyyy-mm-dd
格式的字符串。它不是一个 JS
Date
对象,因为Date
对象实际上不是日期,而是一个时间戳。 它的名字选得不好。 它仅包含一个值,即自 1970-01-01 00:00:00.000 UTC 以来的毫秒数。 因此,Date
对象无法准确表示日期(日历上的方块,或用户从日期输入中进行的选择)。因此,更简单的解决方案是将年月日字符串直接发送到服务器,而不是分配任意时间(例如午夜)并在时区之间进行转换。 然后,服务器应该以保留年月日的方式存储它。 例如,大多数关系数据库提供与
datetime
或timestamp
不同的date
数据类型。 如果用户传递日期,则使用date
类型存储日期。 当您稍后检索它时,也只需传回日期即可。 不要指定午夜。 在示例用例中,您可以在 JSON 中来回传递数据,如下所示:这同样适用于以表单 post 或查询字符串或任何其他方式传递数据。 只需传递日期,不要添加任何时间或时区。
“2009-01-01”
不与任何“2009-01-01T00:00:00.000”
" 2009-01-01T00:00:00.000Z"
、"2009-01-01T00:00:00.000-8:00"
等。回到问题的其余部分:
我希望你现在意识到这个问题的前提是有缺陷的。 不使用
Date
对象来达到这一目的。 如果用户只是选择一系列日期,也不会认为用户是阿拉斯加。 据我们所知,这些日期可能打算稍后用于预订日本的酒店住宿。 因此,用户的本地时区是无关紧要的。也就是说,如果我们确实在某些情况下需要额外的时区信息怎么办? 也许我们实际上不是在选择一系列日期,而是在选择会议的日期和时间。 那么我们还需要知道该会议的时区。 它可能与用户的时区相同,或者会议可能在其他位置举行。
如果这是我们需要的用户时区,我们可以使用 EcmaScript Intl API 从浏览器收集该时区。
如果是其他时区,我们必须提供下拉列表或其他机制来选择目标时区。
无论哪种方式,我们都应该为会议存储所选日期、所选时间和所选时区。 我们不应该将其转换为 UTC 时间戳,因为我们无法预测未来。 无法知道负责该时区的政府是否会更改其标准时间偏移或夏令时日期或时间等。
例如,会议是否将于 7 月 1 日下午 2:00 在纽约举行2030,那么我们应该向后端发送如下内容:
例如,如果我将其存储在 MySQL 数据库中,我会使用
datetime
和varchar
数据类型。 如果使用 PostgreSQL,则为timestamp without time zone
和varchar
。 为此,我不会在 MySQL 中使用timestamp
或在 PostgreSQL 中使用timestamp with time zone
,因为这些类型旨在将值与 UTC 相互转换。摘要
最初的问题是一个带有误导性标题的 XY 问题。 处理纯日期值时应与 UTC 相互转换的假设是不正确的。 相反,以 yyyy-mm-dd 格式将仅日期值作为字符串传递,而不进行转换。
I'll add a new answer to this very old question, because it's referenced often and all the other answers are demonstrating incorrect approaches such as epoch shifting or re-parsing, as described here. Additionally, they're only addressing the title of the question. I'll instead focus on the question body, and ignore the title.
First, note that this format is nonstandard. It should be using two digits for both the month and day components. Leading zeros are required for ISO 8601 compatibility, which is typically expected from date parsers. The dates should be expressed as
2009-01-01
to2009-01-03
.The next error is in the design that "... all dates and times to be in UTC". The user didn't select a date and time, they only selected a date. Whole dates cannot be converted to UTC, because they're not in any particular time zone to begin with. Assuming otherwise is akin to me handing you a paper calendar such as below and asking what time zone it's in.
Of course, none of those days has a time zone, because time is not represented on this device. Each square represents a specific day within the given month and year. If one were to associate time with each day, it wouldn't be a single time, but rather the range of times from the start of the day to the end of the day. Sure, each of those points could be converted to UTC if the calendar were to be read by a person in a particular time zone. But generally we don't go around conveying ranges of timestamps to each-other. Instead we just use a date - so that's what your program should do as well.
This is indeed what happens with the standard HTML5
<input type="date">
tag. Pick a date from below, and notice thatvalue
given is a string in ISO 8601yyyy-mm-dd
format.It's not a JS
Date
object, because theDate
object is actually not a date, but rather a timestamp. It's name was poorly chosen. It contains only a single value, which is the number of milliseconds since 1970-01-01 00:00:00.000 UTC. Thus, aDate
object can't accurately represent a date (a square on the calendar, or the user's selection from the date input).So instead of assigning an arbitrary time (such as midnight) and converting between time zones, the simpler solution is to just send the year-month-day string directly to your server. The server should then store it in a way that preserves the year month and day. For example, most relational databases offer a
date
data type that is distinct fromdatetime
ortimestamp
. If the user passes a date, then store a date, using thedate
type. When you later retrieve it, also just pass back the date. Don't assign midnight. In the example use case, you might pass data back and forth in JSON such as this:The same applies to passing data in a form post or querystring or any other manner. Just pass the date, and don't add any time or time zone.
"2009-01-01"
is not the same as any of"2009-01-01T00:00:00.000"
"2009-01-01T00:00:00.000Z"
,"2009-01-01T00:00:00.000-8:00"
, etc.Going back to the remainder of the question:
I hope by now you realize that the premise of this question is flawed. One doesn't use the
Date
object for this purpose. Nor does one consider that the user is Alaska if they're just selecting a range of dates. For all we know, those dates might be intended to later used to book a hotel stay in Japan. The user's local time zone is thus irrelevant.That said, what if we did need additional time zone information for some scenario? Perhaps instead of picking a range of dates, we're actually picking the date and time for a meeting. Well, then we would also need to know the time zone for that meeting. It might be the same as the user's time zone, or perhaps the meeting is to be held in some other location.
If it's the user's time zone we need, we can gather that from the browser, using the EcmaScript Intl API.
If it's some other time zone, we'll have to provide a drop-down list or some other mechanism to select the target time zone.
Either way, we should store for the meeting the selected date, the selected time, and the selected time zone. We should not convert that to a UTC timestamp, because we cannot predict the future. There's no way to know if the government responsible for that time zone may change its standard time offset or daylight saving time dates or times, etc.
For example, if the meeting is to be held at 2:00 PM in New York on July 1 2030, then we should send to our backend something like:
If I were, for example, storing that in a MySQL database, I'd use the
datetime
andvarchar
data types. If using PostgreSQL, it would betimestamp without time zone
andvarchar
. For this purpose I wouldn't usetimestamp
in MySQL ortimestamp with time zone
in PostgreSQL, because those types are designed to convert values to/from UTC.Summary
The original question was an XY problem with a misleading title. The presumption that one should convert to/from UTC when working with date-only values is incorrect. Instead, pass date-only values as strings, in
yyyy-mm-dd
format, without conversion.我知道这个问题很旧,但正在研究同一问题,一种选择是将 date.valueOf() 发送到服务器。 javascript Date 的 valueOf() 函数发送自 UTC 1970 年 1 月 1 日午夜以来的毫秒数。
valueOf()
I know this question is old, but was looking at this same issue, and one option would be to send date.valueOf() to the server instead. the valueOf() function of the javascript Date sends the number of milliseconds since midnight January 1, 1970 UTC.
valueOf()