I've gotten a response from one application with the following date & time format:
yyyy-mm-ddT00:00:00.000Z
I need date and time for a report I have to present. What does the .000Z mean? What do I need to do to get the time according to a region using javascript?
.000 is the fraction of a second and Z indicates UTC timezone.
How you convert to your local time will depend on which programming language you prefer, but for example Perl has standard modules for parsing and formatting times.
Related
I want to force clients (web, android, ios) to send the API only time in UTC/GMT.
This means that they get user's local time (using any method), convert it to UTC/GMT, and then send it to the API.
And I want to reject any datetime parameter that is not in UTC/GMT.
In JavaScript, I can get UTC this way:
new Date().toUTCString() which gives this result:
'Mon, 15 Nov 2021 04:26:38 GMT'
And I send this string to the API:
[HttpGet]
public object Parse(string clientDateTime)
{
var date = DateTime.Parse(clientDateTime);
return new
{
ParsedDate = date,
Kind = date.Kind.ToString()
};
}
However, I see that .NET parses this date time as Local and not as Utc. This is in spite of the string containing GMT.
How can I check the incoming datetime and make sure it's UTC/GMT?
You can greatly simplify your problem by using a conventional format for datetime serialization. A common choice for this problem is using the ISO 8601 datetime format.
Here you can find an in depth explanation of this format, but as an example this is a datetime in the ISO 8601 format: 2021-11-15T06:40:48.204Z (the final Z indicates that the datetime represented by this string is UTC)
The main advantage in fixing a format for date and times is that you will know in advance the format and you will be in a much better position to parse the datetime strings on the server.
Using the ISO 8601 format is a good choice, because it is a well known format and it is the standard de facto for the datetime serialization: this basically means that anyone writing a client for your application will be able to comply with the required format. Of course, you are required to clearly document this convention so that your clients (or your fellow developers) will be aware of it.
Another tip is using the DateTimeOffset struct instead of DateTime. DateTimeOffset is basically used to represent a specific point in time and that's exactly what you want: your clients will send you ISO 8601 strings representing a point in time and you want to know that point in time in your application.
Your clients will be able to use any time zone to express the point in time they want to send to your application. Doing this using an UTC datetime or any other time zone is just an implementation detail. Once you have parsed the datetime string to a DateTimeOffset instance, if you really want to, you can check whether it is an UTC time by checking the Offset property: it will be a zero TimeSpan value if the DateTimeOffset instance represents an UTC date and time.
In order to manipulate date in a Javascript client application I strongly suggest to use the Moment.js library. Check this docs to see how to get an ISO 8601 string with Moment.js
You can use this helper method to parse an ISO 8601 string to a DateTimeOffset instance. This implementation allows the client to send you a broad range of ISO 8601 compliant string formats, if you want you can be stricter by reducing the number of allowed formats (see the Iso8601Formats static field in the code).
To summarize:
ask your clients to only send you datetime strings in a format compliant with the ISO8601 specification. Clearly document this choice
for a Javascript client use a library like Moment.js to manipulate date and times. This will be much simpler than using plain old javascript Date objects.
if you are manipulating date time strings representing a specific point in time, use the DateTimeOffset struct instead of the DateTime struct. DateTimeOffset represents a specific point in time expressed in a certain time zone. The Offset property represents the difference between the point in time represented by the DateTimeOffset instance and UTC: its value will be a zero TimeSpan if the DateTimeOffset instance represents an UTC datetime. Notice that the point in time will always be the same regardless the time zone it is referring to, so using UTC doesn't make any real difference (it's just an implementation detail at this point).
use code like this one to parse a DateTimeOffset instance from a string. This code tries as many ISO 8601 compliant formats as possible (this is done in order to accept as many valid formats as possible). If you want, you can decide to be stricter: to do that, just reduce the number of formats in the Iso8601Formats array.
A final note on your code. The behaviour you are observing from DateTime.Parse is exactly the expected one. Check the documentation for DateTime.Parse:
Converts the string representation of a date and time to its DateTime
equivalent by using the conventions of the current thread culture.
DateTime.Parse is basically designed to use the locale settings of the machine running the code.
If you want to learn more on the difference between DateTime and DateTimeOffset you can check this stackoverflow question.
Is there a way to send data from the client to a server without adjusting the time to account for the time zone difference between the client and server?
I have an angular app with a nodejs server. When I send a date from a form to the server via an HTTP request and log the date on the server, the date changes to the time in the time zone of the server.
I'd like to send the date object back and forth without it changing.
I always use http://momentjs.com/ when dealing with javascript dates. When a date object is created the systems timezone is used, so you'll always have to adjust for the offset. The easiest solution is to do one of the following
use a string and parse it
use moment().format() with a custom format
use UTC on the client and server
use ticks or unix epoch
There really isn't a great solution, you just need to be consistent.
Use milliseconds .
let now = new Date();
let time = now.getTime();
time contains number of milliseconds in UTC timezone always. In the server you can convert milliseconds to date . This way you dont need to worry about timezones.
According to MDN Javascript Date objects are constructed using UTC.
You can send the date object back and forth without ever changing it, it will simply be interpreted relative to the 'locale' of wherever it is being used.
If you'd like to maintain the local date and time irrespective of location (between different client and server locations) you'll probably need to pass along the locale of the Date as well as the Date itself.
A way to do this is to format your Date as a string in ISO 8601 format with a time offset (like +0100.)
That way you'll get both the local time and the offset used for every time.
You can construct it by hand using the Date.prototoype.toISOString method but that will still be relative to UTC.
Here's another Stack Overflow question on how to get the correct offset yourself.
I am based in the UK so when I attempt to parse a new date in JavaScript as follows:
new Date('2016-06-03T09:05:15');
Results in the following date:
Fri Jun 03 2016 10:05:15 GMT+0100 (BST)
I want the date to be parsed as is, and for no locale adjustments (in this instance, BST) to occur. Is this achievable without writing my own date/time parser?
I want the date to be parsed as is, and for no locale adjustments (in this instance, BST) to occur
That is exactly what should occur, however it doesn't in all browsers. You should not parse strings using the Date constructor or Date.parse (they are equivalent for parsing). Always manually parse strings, a library can help but usually isn't necessary.
According to EMCAScript 2015, '2016-06-03T09:05:15' should be parsed as a "local" date (i.e. based on the host system settings for date, time and time zone on the date and time supplied). A Date object's time value is UTC, so when creating the time value, the host settings are taken into consideration. The same settings are also used for output, so if the OP string is correctly parsed and then written to output, you should get back exactly the same date and time (though probably in a different format).
If you're seeing a different time from the input string, then the string isn't being correctly parsed (hence advice to manually parse strings).
Is this achievable without writing my own date/time parser?
Yes, use a library that someone else wrote. However, if you also want host settings to be ignored for output, you'll also need to write your own formatter, or use a library.
The good news is that there are many to choose from.
the data in the DB look like this
2011-09-07 14:43:22.520
But my Web API outputs the data and replace the space with the letter T
2011-09-07T14:43:22.520
I can replace the letter T with a space again in jquery, but can I fix this problem from the Web API (make the web api output the original data?)
I also do not want the miliseconds at the end. How can I get rid of them?
The format of how you see the date in the database is usually irrelevant, because it should be passed into .Net as a DateTime - not as a string. (If you are storing it as a varchar in the database, you have a bigger problem.)
ASP.Net WebAPI is returning the value in format defined by ISO8601 and RFC3339. This is a good thing, as it is a recognized machine-readable format. You probably don't want to change it.
If you really want to change it, you would need to implement a custom JSON.Net JsonConverter, deriving from DateTimeConverterBase. This is discussed here and here.
But instead, you should consider how you are using the actual result in your client application. You mentioned jQuery, so I will assume your consumer is JavaScript. In many browsers, the ISO8601 value that you have is already recognized by the JavaScript Date constructor, so you might be able to just do this:
var dt = new Date("2011-09-07T14:43:22.520");
But this won't work in all browsers. And Date doesn't have a whole lot of flexibility when it comes to formatting. So instead, you might want to consider a library such as moment.js. With that in place, you can do this:
var m = moment("2011-09-07T14:43:22.520");
var s = m.format("YYYY-MM-DD HH:mm:ss"); // output: "2011-09-07 14:43:22"
Please note that the format string here conforms to moment.js, not to .NET. There are differences in case sensitivity. Please refer to the moment.js documentation for details.
One other thing - since the value you provided doesn't have either a Z at the end, nor does it have an offset such as -07:00, then I assume it came from a DateTime whos .Kind value is DateTimeKind.Unspecified. You should be aware that when this gets sent into JavaScript (or anywhere else for that matter), there is no information about what time zone is represented. JavaScript will assume the local time zone of the browser.
If that's not what you had intended, then you need to store UTC values in your database, and make sure they have DateTimeKind.Utc so they get serialized with a Z at the end. JavaScript will normalize this to the browser's time zone, but you will still be talking about the same moment in time.
Alternatively, you could use a DateTimeOffset type - which would serialize with the specific offset. JavaScript will still normalize this to the user's time zone.
I have a service that returns a date. The weird thing is that most of the time it comes back like this: /Date(1364227320000)/
but sometimes it returns the date like this /Date(1364050020139-0400)/
when I open up the visual studio debugger, the dates look the same for each one (minus differences in time)
What could account for this difference?
This is handled in System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTimeInDefaultFormat(). If the DateTimeKind is Unspecified or Local, it adds the UtcOffset to the end (the -400 part, meaning Utc - 4 hours).
It depends on the kind of the DateTime object (i.e., the value of its Kind property). If you're returning a DateTime with DateTimeKind.Utc, there will be no offset. If the date time is of kind Local or Unspecified, the offset will be written out.
You can find more information about the format in the "DateTime Wire Format" section of the "Stand-Alone JSON Serialization" page on MSDN.