Handling date objects javascript vs java - javascript

I have an date input field. The user inputs a date then submits and this date is saved in the database. I have two options on how to do things and I know how to implement both but I'm not too sure what the best practice is as I'm a noob.
Option 1: Take the value read from the date input which is a string and send that to my Spring back-end and then create a date object.
Option 2: Take the value read from the date input and create a Date object in JavaScript and send a date object to my spring controller.
I'm leaning towards option 1 because I'm thinking I will have better error handling in my controller?

Your Question is moot as you will be sending a string of a date back to the server either way.
ISO 8601
Generally best to use the standard ISO 8601 formats when exchanging date-time values as text. For a date that would be YYYY-MM-DD.
java.time
As for performing date-time related work on that date value, I recommend using Java for that. Java offers the industry-leading date-time framework found in the java.time classes, defined by JSR 310. See Oracle Tutorial.
The java.time classes conveniently use the ISO 8601 formats by default when parsing/generating date-time strings.
LocalDate ld = LocalDate.parse( "2019-01-23" ) ; // Parses standard ISO 8601 strings.
String output = ld.toString() ; // Generates "2019-01-23".

Related

How to reject non UTC/GMT dates from client in C#?

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.

How do I accept multiple formats of date with moment.js

I want to accept dates from the users but I cannot enforce the users to enter the date in a specific format. I have tried going through the momentjs documentation but couldn't really find how its done. I can specify an array of formats but then I'll be tied down to those specific formats only.
I know that MS Excel and many other apps does this. (Take date input in some format and convert it to the application suitable format)
If not with moment.js how else can I achieve this? What could be the algorithm or logic that can achieve this thing.
Thanks!
Moment.js can parse an ambiguous string as a date if you don't specify expected formats. It will first attempt to parse it as an ISO 8601 date format, then as an RFC 2822 format and ultimately fall back to JS Date parsing. Keep in mind the supported formats in a JS Date are inconsistent between browsers.
For this reason it's highly advised to always parse using a set of expected formats and enforce the user to input in one of these. Otherwise you may end up with incorrectly parsed dates.

Angular and moment.js : should I convert fields taken from json string to Date or moment.Moment?

I have following data structure returned from api call (when editing user profile):
export class User {
username: string;
email: string;
creationTime: Date;
birthDate: Date;
}
I also use Angular Material DatePicker for editing this value (birthDate). I need to validate date after user enters it (in frontend) and also parse it from string to Date/moment.Moment and back to string when sending value to backend. What is more preferable way to declare it as model class field? Should I use native Date type and use moment.js just for manipulation of dates or is it more convenient to just use moment.Moment as type without using Date type at all?
What with creationTime if I want just to display it for user, should I just declare it as string type in frontend?
And last question - should the conversion take place in service call to backend api (while parsing output, e.g. with reviver function) or is it somewhat better to convert strings in model constructor call?
This is what the documentation says:
Setting the selected date
The type of values that the datepicker expects depends on the type of DateAdapter provided in your application. The NativeDateAdapter, for example, works directly with plain JavaScript Date objects. When using the MomentDateAdapter, however, the values will all be Moment.js instances. This use of the adapter pattern allows the datepicker component to work with any arbitrary date representation with a custom DateAdapter. See Choosing a date implementation for more information.
Depending on the DateAdapter being used, the datepicker may automatically deserialize certain date formats for you as well. For example, both the NativeDateAdapter and MomentDateAdapter allow ISO 8601 strings to be passed to the datepicker and automatically converted to the proper object type. This can be convenient when binding data directly from your backend to the datepicker. However, the datepicker will not accept date strings formatted in user format such as "1/2/2017" as this is ambiguous and will mean different things depending on the locale of the browser running the code.
https://material.angular.io/components/datepicker/overview
So if your dates are ISO 8601 strings then you don't have to convert anything.

Universal DateTime Format

I'm working on an application where I'm sending datetime from JavaScript (client side) to a Web Service (server side). Now problem with DateTime is it has many formats and at any instance client might have a different format of DateTime than of server, which might break the parsing of datetime on server side.
I was thinking may be JavaScript's function "getTime()" will be an equivalent of C#'s datetime property "Ticks", so that I can sent getTime() from front end and can easily parse it to valid DateTime on server end. But unfortunately that doesn't seems to be the case :(
So is there any universal format that I can use for DateTime that would take my worries away of client's format being different and server responding with 500?
UPDATE
I can get into practice of sending "YYYY-MM-DD" or any other pre-defined format from front end and parse accordingly on back end, but it's viable only till someone misses it, and as a project gets bigger and more devs starts working on it, practices like this becomes overhead on management. So in short it is a work around but not a bull's eye solution. Thanks Mohit for bringing it up I forgot to mention.
I'd suggest the following:
Use JavaScript UTC clientside to send up to the server http://www.w3schools.com/jsref/jsref_utc.asp Or use a date format that cannot be confused (i.e. Long date or "yyyy-MM-dd")
On the server store the dates in UTC
When sending dates clientside send UTC dates to the client and use a JavaScript library like http://momentjs.com/ to render dates clientside in the client's time zone.
in my option , this is not pertain to time format or team convention or other something .
The real question is why you handle time with "String" , not "Date",
you get a Date object ,and turn it to String object , do some operation with string(what is boring and dangerous),and then turn it as Date() (or DateTime in C#) back .
string is string , time object is time object .
the only moment we do date=>string action is showing to end user , as possible as,we handle it by time object and use some stable tools to translating
for example: we have a dateTime object in c#,and we response it to client,
this is its format,the most standard format :
CreateTime: "/Date(-62135596800000)/"
and it will be translated as a Date object in js . with this , you don't need care UTC or local ,yyyy-MM-dd or yyyy/MM/dd . with some date lib , you can do anything to it as you want in a standard base line . after your all strange operation ,it is still a date object ,still a standard format,and transport it to service side ,it will be a DateTime object(still a standard format) in C# .
if you need get date from some other source like user input,
No matter what you want to do next,first and first translate it to a date object.

formatting ISO date

I have making an API call and getting response.
The response has datetime value like this
20131107T102103,00+01
I guess this is ISO date format. I am not able to format it to human readable format using javascript.
This is indeed ISO 8601, but it's not exactly the most common form of it.
This is the compact form. On the web, we usually see the extended form, which is also described in RFC 3339.
It's using a comma instead of a decimal in the seconds field. While either are allowed by the ISO 8601 specification, most implementations use a decimal point.
While ISO 8601 allows for a shortened form of the offset (+01), typically this is expressed in the compact form as +0100, or in the extended form as +01:00.
Nonetheless, the value is ISO 8601 compliant, so it should be parseable by most newer browsers. But it's not.
Internet Explorer 11
Google Chrome 35
Firefox 30
So, what to do then? You can write a bunch of code to pull out all the individual parts of the string and build a Date object yourself, but that's too much work. Just use moment.js. This is one of the leading libraries for parsing and formatting date and time in JavaScript, and it works in all browsers.
// parse it to a moment object first
var s = "20131107T102103,00+01";
var m = moment(s + "00","YYYYMMDD[T]HHmmss[,]SSZZ");
// then you can output however you like
m.format("...whatever...")
// or perhaps you need a JS Date object
m.toDate()
Notice that I still had to add two extra zeros to the offset. Even moment.js doesn't recognize offsets with only two digits.
date_default_timezone_set('America/New_York');
$d1=new DateTime('20131107T102103,00+01');
$date = DATE_FORMAT($d1,'Y-m-d H:i:s');

Categories

Resources