Serialize an IEnumerable<DayOfWeek> to a javascript client in which format - javascript

I send an IEnumerable to a javascript client. I would like to know what is the best format to send those values to the client that the consumption and computation with those values works best with angularJS itself or the angularjs/moment.js library?
Send the values as integers 0,1,2,3,4,5,6 or Sunday/Monday/Tuesday etc...

I think dayOfTheWeek value can be sent as an integer. As, it is treated the same way in JS only i.e as integer..
JS
var d = new Date();
console.log("date is ->",d," and day of the week is->", d.getDay());
console.log("Now changing date");
d.setDate(4);
console.log("date is ->",d," and day of the week is->", d.getDay());
Output
date is -> Wed Jan 01 2014 19:46:07 GMT+0530 (India Standard Time) and day of the week is-> 3 VM331:3
Now changing date VM331:4
date is -> Sat Jan 04 2014 19:46:07 GMT+0530 (India Standard Time) and day of the week is-> 6
So it will be a better to have an integer, for lowering the network traffic too.

"Best" is subjective, but I will give you my opinion.
From a raw JavaScript perspective, the day of the week is 0 (Sunday) through 6 (Saturday). You can see that in the MDN docs. It aligns exactly with C#'s DayOfWeek enumeration, so you certainly can pass that, but I wouldn't recommend it, for a few reasons.
What are you going to do with it in JavaScript once you have it? The Date object has a getDay(), but it doesn't have setDay(), so you can't adjust an existing date to a particular day of the week unless you're going to do your own computation or use a library like moment.js.
Moment.js has a day function for that, so you could pass it like this:
moment().day(0);
But you could just as easily pass the full day name:
moment().day("Sunday");
Or you could use another function if you needed Sunday to be represented by a 7
moment().isoWeekday(7);
That brings up an interesting point, which is that the standard for dates and times is ISO-8601, and that standard uses weekdays numbered 1 through 7. If you're going to send data out of your application in numeric form, shouldn't it conform to a standard? I think so, but then again - who's to say that the consumer of this data will understand that that standard is in use? With just a simple integer, it can be really hard to tell.
Then think for a second about JSON serialization. The JSON format was designed to be more compact than XML, but still be human readable. Which of these looks more readable to you?
{ days: [0,1,2] }
or
{ days: ["Sunday", "Monday", "Tuesday"] }
Not convinced? How about when passing a full date and time?
{ date: 1388453025678 }
or
{ date: "2013-12-31T01:23:45.678Z" }
Clearly, the second choice is more human readable in both scenarios.
In general, it's an accepted practice to serialize C# enums as strings rather than as integers, because otherwise they can lose their original meaning. In the above example, what if I had called the variable foo instead of days. With the numeric form, you'd have no idea what the data was representing.
Therefore, my recommendation would be to pass the string version. There are lots of advantages, and there are only two disadvantages I can think of, which are:
The numeric form is more compact - but that's not what JSON aims for anyway. If smaller data is what you're after then you'd probably be better off with a binary serialization format like Google's Protocol Buffers. But that's usually overkill - I wouldn't go down that road unless other parts of your application demanded it.
The weekday names are in English. Personally, I don't think that's so bad in the JSON itself, but some might prefer that be localized. You can always do it later though:
moment().day("Sunday").lang('fr').format("dddd"); // "dimanche"
You also mentioned Angular.js, which does have a date filter, but you're not going to be able to bind just a day of week to it either way. So that doesn't really factor into the decision.

Related

Using moment.utc() incorrectly converting the date into utc format of "days" format-Moment Javascript

I'm using moment library to convert date into a utc format. here is my date string:
var dateString = "2019-01-31T11:33:16.952+0000";
new Date("2019-01-31T11:33:16.952+0000") // o/p: Thu Jan 31 2019 03:33:16 GMT-0800 (Pacific Standard Time)
since this date is less than a week from today's date, I'm trying to display a text saying "n days ago" instead of actual date. But for some reason I'm getting a future date displayed as "6 days ago" when I do this:
moment.utc("2019-01-31T11:33:16.952+0000").local().fromNow() // shouldnt this display "5 days ago"??
Not sure why moment is not converting the date correctly, any ideas what could be wrong here?
I guess(Considering use of local() converts to your local timezone so time is deducted because you might be in -ve TimeZone) this answer is a solution you're expecting:
Ideally, you would want to pass a UTC timestamp from your server to
the client. That doesn't mean you have to switch your whole server
over to UTC, it just means that you would convert from the time in
your database to UTC on the server before sending it over the web.
Sure, it would be even better if you actually stored times in UTC, but
you said you aren't in a position to make that sort of change right
now. But let's just work off the assumption that you can't change
anything at all on the server.
We'll also assume that your server is fixed to the UTC-07:00 offset.
In real life, this would only be true for places like Arizona that
don't follow daylight saving time. So if you are in Los Angeles and
are in Pacific Time, then some of your data is based on UTC-07:00, but
some of it is based on UTC-08:00. That requires a lot more work if you
want to do it in JavaScript.
Let's also assume that the input is already a string in ISO8601
format. (If it's not, then let me know and I will adjust this code.)
var s = "2013-09-11 18:00:00"; // from action.timeStamp
var actionTime = moment(s + "-07:00", "YYYY-MM-DD HH:mm:ssZ");
var timeAgo = actionTime.fromNow(); The reason your other code didn't
work is because in the first line, you are affected by the time zone
of the browser. The zone setter in the second line just changes the
zone for formatting, not changing the actual moment in time.
Also, when you dump a moment to the console for debugging, make sure
you format it for output. Otherwise you are just looking at its
internal property values, which may or may not make sense directly.

How to change only timezone without modifying the time in momentz

I have date and time in 2016-06-21T10:00:00-07:00 format which represets 06/21/2016 5 PM in PST, I just want to change this to 06/21/2016 5 PM in EST and vice versa. How can I do it with momentz?
JSFiddle
debugger;
var dateTime = moment('2016-06-21T10:00:00-07:00');
var newDateTime = dateTime.clone();
newDateTime.tz('US/Eastern');
//dateTime = dateTime.utc();
console.log(dateTime.utcOffset());
console.log(newDateTime.utcOffset());
console.log(newDateTime.utcOffset() - dateTime.utcOffset());
//console.log(utc.format());
dateTime = dateTime.add(newDateTime.utcOffset(), 'minutes');
console.log(dateTime.format());
console.log(new Date(Date.parse(dateTime.format())).toJSON());
EDIT:
given input = 2016-06-21T08:00:00-07:00 (PST)
expected output = 2016-06-21T08:00:00-04:00 (EST)
So when I convert that to UTC then it should become
2016-06-22T15:00:00Z for PST
2016-06-22T12:00:00Z for EST
I think you are confused about how ISO8601 format works. This format always represents local time with a time zone offset. Thus 2016-06-21T10:00:00-07:00 represents June 21 2016 at 10 AM in a timezone that is currently UTC-7 (this could be US pacific, among many others).
It sounds like you want to take the local time, but put it in a new timezone. This opens up some interesting questions about why you are receiving the date in the format that you are. If the date is meant to be interpreted as an exact point on the global timeline, then the format you are receiving it in is good. If however, the date is meant to be interpreted as a local time (not relative to UTC), it might be worth considering the possibility that the format of the date needs to be changed at the source. For instance, if you are making an ajax request to an API, and it is returning a date in this format, but that date actually has no relationship to UTC, it would be good to try to change that API to only send the local time (without the offset). If you were able to do that, then the following code would work:
moment.tz('2016-06-21T10:00:00', 'America/New_York').format()
"2016-06-21T10:00:00-04:00"
If you are unable to do that, or if the date is meant to be interpreted as an exact point on the global timeline, but you wish to ignore that in your specific use case, that can be done. You will need to specify a parse format that ignores the timezone offset on your initial time stamp. The code would be as follows:
moment.tz('2016-06-21T10:00:00-07:00', 'YYYY-MM-DDTHH:mm:ss', 'America/New_York').format()
"2016-06-21T10:00:00-04:00"
You might benefit from the material in this blog post, as it covers how ISO8601 format works, and how all of moment's constructor functions work.
Checkout moment().utcOffset() You can pass in the offset as parameter to this function and the date would use that locale.
Assuming you know beforehand the utcOffsets required which in your case are -420 and -240 or -300(EST with DayLightSaving). Below can be done
var dateTime = moment('2016-06-21T10:00:00-07:00');
dateTime.utcOffset(-420).format();
"2016-06-21T10:00:00-07:00"
dateTime.utcOffset(-240).format()
"2016-06-21T13:00:00-04:00"
NOTE: With -04:00, it should 13:00:00 and not 07:00:00 - http://www.timeanddate.com/time/zones/est
EDIT: This answer was posted to the earlier version of question, where same time was needed in different timezones. If it is incorrect, kindly please elaborate on how it is.
Thanks!

Javascript: Difference between `new Date(dateString)` vs `new Date(year, month, day)`

Referencing to the accepted answer on this question How do I get the number of days between two dates in JavaScript?. I see, in the function parseDate:
function parseDate(str) {
var mdy = str.split('/')
return new Date(mdy[2], mdy[0]-1, mdy[1]);
}
He is doing this:
var mdy = str.split('/')
return new Date(mdy[2], mdy[0]-1, mdy[1]);
i.e. splitting the passed date into month, day and year and then passing it on to Date like new Date(year, month, day) while he could simply do new Date(str) and it would have returned the same result (Wouldn't it?). Can anyone please explain the difference between both the ways?
Update: Test results:
var str = '1/1/2000'
var mdy = str.split('/')
console.log( new Date(str) ) // Sat Jan 01 2000 00:00:00 GMT+0500 (Pakistan Standard Time)
console.log( new Date(mdy[2], mdy[0]-1, mdy[1]) ); // Sat Jan 01 2000 00:00:00 GMT+0500 (Pakistan Standard Time)
No, they're not the same (even assuming you'll subtract one month later: he's doing mdy[0] - 1) because new Date(str) is required (by standard, see §15.9.4.2) to accept only date in a specific format ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ, see also this post, I won't repeat myself here):
If the String does not conform to that format [ISO 8601] the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
Please note (as pointed out by Royi in comments) that also RFC 2822 should be supported (according to MDN) but it's not mentioned in JavaScript specifications and Internet Explorer doesn't officially support it (see MSDN, it can parse something similar but it's not the same).
In that code they're parsing using a specific locale rules (MM/DD/YYYY, I suppose en-US locale but it's not only one). To be honest I wouldn't even use that code for parsing (because yes, actually it'll be broken for a different locale: even separator used for splitting is not "locale safe"). Let me explain with an example:
You're using a proper configured date time picker (or <input type="date"/> when supported) you'll enter date according to your locale. For example in Italy (but in general in Europe) we write DD/MM/YYYY.
Now let's imagine that user picked 21 December 2014 (formatted as 21/12/2014 according to his locale).
With string splitting that code will fail (because it'll pick 21 as month number, obviously it's not valid). Even worse than that such errors may even go unnoticed (for example if user picks 1/2/2014 code will "think" it's 2nd Jan but user picked 1st Feb). Do you want to make it more complicate? Even new Date(str) may fail because it's browser dependent (and you can't really trust heuristic to be portable and safe).
If you're asking yourself "Then why they used such code?" I'd say that they used a quick workaround to support dates using en-US locale (probably because browser they used didn't support them with heuristic guess) but it's not something you should reuse.
Solution? Do not ever parse date by hand (unless you really and deep know what you're doing), use a good library (for example moment.js) for that because most assumption you may do about date formatting are...wrong.
I tried to enter your test code into jsperf.com, and the results on my machine are clear, and they say that you should not try to split the string.
I tried two tests for the test using a split string, and supprisingly, the split itself was not what was taking up the time.
Try for yourself at http://jsperf.com/date-from-string-or-dateparts

javascript timezone format

I need to format a javascript Date to send via json to the server. The server expects the time to be in the format according to this example
2011-08-31T06:49:28.931 -0700
which it conveniently tells me when I try to submit something like
2011-08-31T06:49:28.931 -07:00
The trouble I am having is with the timezone part, -0700. I've been looking at the Date API, and don't see a way to specify the timezone format. I can do d.getTimezoneOffset, but it returns 240 (Im in EDT I think) for me.
So, I can convert 240 to 0400 to represent 4 hours. I am worried however about correctness for other timezones. My questions are
1) How to convert the result of the getTimezoneOffset() into the required format, and how to determine what the sign should be (thats the part I am worried about)?
2) Is there a way to get the format off the date object itself so I don't have to do anything custom? If i do d.toString() I get "Wed Aug 31 2011 09:48:27 GMT-0400 (EDT)", so here the timezone part is in the format I want. So it might be possible. Maybe the best solution is to just use a regex to grab the timezone off d.toString()...
3) Extra credit: is the format the server requires some sort of standard?
Update: using match(/^.*GMT(-?\d*)/) returns "-0400" at index 1 of the array. Perhaps I should just use that? Im wondering if that regex will work for all timezones in the context of the sign.
Try this code:
var d=new Date(Date.now()); // sets your date to variable d
function repeat(str,count) { // EXTENSION
return new Array(count+1).join(str);
};
function padLeft(str,length,char) { // EXTENSION
return length<=str.length ? str.substr(0,length) : repeat(String(char||" ").substr(0,1),length-str.length)+str;
};
var str=padLeft(String(d.getFullYear()),4,"0")+"-"+
padLeft(String(d.getMonth()),2,"0")+"-"+
padLeft(String(d.getDate()),2,"0")+"T"+
padLeft(String(d.getHours()),2,"0")+":"+
padLeft(String(d.getMinutes()),2,"0")+":"+
padLeft(String(d.getSeconds()),2,"0")+"."+
d.getMilliseconds();
//str+=" GMT";
var o=d.getTimezoneOffset(),s=o<0?"+":"-",h,m;
h=Math.floor(Math.abs(o)/60);
m=Math.abs(o)-h*60;
str+=" "+s+padLeft(String(h),2,"0")+padLeft(String(m),2,"0");
alert(str);
You might want to use one of the date/time formatting libraries that bakes in support for this timezone format (such as http://jacwright.com/projects/javascript/date_format/). In any case, you're right: there really is no good way to control the format output.
As far as the regex goes I don't know that all browsers consistently use the GMT string format, so that may not be the best path forward.

Regular expression to match Date

I am trying to validate following date format through regExp, but still i didn't get ant working solution-
ex.-
OCT-12-2011
FEB-06-1995
how can i do it using regexp.
Thanks in advance!!
Date JS is the first hit on Google.
Comprehensive, yet simple, stealthy and fast. Datejs has passed all trials and is ready to strike. Datejs doesn’t just parse strings, it slices them cleanly in two.
Sample code from their site:
Date.parse('today');
Date.parse('t + 5 d'); // today + 5 days
Date.parse('next thursday');
Date.parse('February 20th 1973');
Date.parse('Thu, 1 July 2004 22:30:00');
The only downside is that it modifies the prototype of build-in Date object. Although it's considered a discouraged practice I doubt that these particular additions will affect you application. There are still plenty of sites using Prototype without any problems.
EDIT: ragarding parsing Date values via RegExps.
Be very careful especially considering different date.toString() implementation in different browsers. Here's what new Date().toString() gave me:
IE9: "Mon Jul 11 14:50:45 UTC+0300 2011"
FF5: "Mon Jul 11 2011 14:51:08 GMT+0300 (FLE Daylight Time)"
If you get those strings from the server and you feel that adding a library just for dates is an overhead you'll be fine with regular expressions.
Don't try to validate it very strictly using a regex. Check the format, using something like this:
[A-Z]{3}-[0-9]{2}-[0-9]{4}
Then, check each part to see whether that part is valid.
... not sure how strictly you want to do this.
var months = [
'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'
],
regValidate = RegExp('^(?:' + months.join('|') + ')-[0-3][0-9]-\\d{4}$');
alert(regValidate.test('OCT-12-2011'));
Depending on you requirements, the following could do:
^[A-Z]{3}-\d{2}-\d{4}$
Or more elaborate:
^(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(0[1-9]|[12]\d|3[01])-[12]\d{3}$
Or anything in between :) (You may even elaborate further on the year part.)
If you want to do it with a single regexp, you could use something like:
/^(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-([012]\d|3[01])-[12]\d{3}$/
This will not match a date before JAN-01-1000 or after DEC-31-2999.
Note: do not forget to check for invalid february dates like FEB-30-2011

Categories

Resources