Date difference calculation in C# vs Moment.js - javascript

I was doing calculation on two dates. I need to find how much days left for the user to use their contract in the site. I have expiry date stored in the DB. And I need to compare this with the current date and get the remaining days left to enjoy their subscription.
Initially this number of days remaining calculation was in the C#.
var daysLeft = Convert.ToInt32((data.expiryDate.Date - DateTime.Now.Date).TotalDays);
//Say, the expiryDate is Thu Dec 31 2020 00:00:00 GMT+0530 (India Standard Time), And daysLeft is 220 for the above statement
And Now i tried the same in Moment.js in client side.
moment(data.expiryDate).diff(moment(), 'days')
//Say, the expiryDate is Thu Dec 31 2020 00:00:00 GMT+0530 (India Standard Time) and it is giving 219.
I also tried like subtracting two dates in same format after converting it to YYYY-DD-MM as below which is giving the error
moment(data.expiryDate).format('YYYY-DD-MM').diff(moment().format('YYYY-DD-MM'), 'days')
Object doesn't support property or method 'diff'
Why in C# its 220 and in moment.js it is 219? Am I missing anything? Please suggest me where the calculation goes wrong.

When you do this in c#:
data.expiryDate.Date - DateTime.Now.Date
you actually substract whole days (because .Date results in time being 00:00:00.000).
Now, you do the Following in js:
moment(data.expiryDate).diff(moment(), 'days')
and the difference here is that you substract date & time.
Note (use of .Now without .Date):
var expiryDate = DateTime.Parse("12/31/2020 10:00:00");
Console.WriteLine((expiryDate.Date - DateTime.Now).TotalDays);
returns 219.654703995023 when the same code with .Date returns 220
TL;DR:
---------------------------------------------------------------
| moment.js | C# |
---------------------------------------------------------------
|moment() | DateTime.Now |
|moment().startOf('day')| DateTime.Today (=DateTime.Now.Date) |
---------------------------------------------------------------
If you want the same result for your javascript part, you should probably use .startOf('day') (which seems to be the equivalent of .Date according to Moment.js | Home)

In C#, TotalDays represents whole and fractional days, the return type is double. And convert to int will round to the nearest 32-bit signed integer.
In moment.js, diff will truncate the result to zero decimal places, returning an integer.
But before 2.0.0, diff returned a number rounded to the nearest integer, not a truncated number.

Related

How to resolve loss of minute precision formatting a moment in 12HR?

I've converted an ISO date string to a momentjs moment and then formatted that moment using .format("MM/DD/YYYY HH:MM").
When I output the final formatted moment, the minute value is incorrect as against the value read back from the iso string originally.
In this case the ISO string value holds 3:10 PM or "2016-08-03T03:10:00.000Z" as represented in the string. But when I call format the moment value is 4:07PM meaning three minutes have been subtracted during the format.
During debug I noted the following values at each assignment stage:
Step 1 (converting the db value to an ISO string):
var actualBCR_Local = moment.utc('#Model.Escalation.Actual_BCR_ISO').toISOString();
value: "2016-08-03T03:10:00.000Z"
Step 2 (converting the ISO string to a momentjs moment in order to represent the local time GMT+1):
var actualBCR_Local_Moment = moment(actualBCR_Local);
value: Wed Aug 03 2016 04:10:00 GMT+0100 (GMT Daylight Time)
Step 3 (formatting the moment in 12HR format for presentation, issue is here as I lose 3 minutes as against the original value which should be 04:10):
var actualBCR_Local_Formatted = actualBCR_Local_Moment.format("MM/DD/YYYY HH:MM");
value: "08/03/2016 04:08"
How can I prevent loss of minute precision when formatting a moment in 12HR format?
that's because you use the wrong format
In this section, you will find out that you are using HH:MM which means hour:month
If you use HH:mm then you will get correct time.
and that's why you got 2 minute loss, cause it display 08 as "month"
here is the what I tested

How do I prevent javascript from converting my dates to GMT?

I have a timestamp given by
timestamp = 2015-02-22T10:00:00.000Z
Why is it converted to GMT when I do this
var dt = new Date(timestamp);
console.log('dt = ' + dt); // prints Sun Feb 22 2015 05:00:00 GMT-0500 (EST)
I don't want it to convert my date to GMT. How do I prevent javascript from converting my dates?
When you try to execute dt = ' + dt, Javascript tries to convert the dt object to a string so it can be added to another string. It does that by calling the dt.toString() method and the format you are seeing is the default string conversion for a date object.
FYI, this default format that looks like this:
Fri Mar 06 2015 19:24:42 GMT-0800 (Pacific Standard Time)
is NOT GMT time. The time value shown is local time. It is showing you that local time shown is -0800 hours from GMT, but the time itself is expressed in local time.
It's not uncommon to want to just truncate off the last part of this and display:
Fri Mar 06 2015 19:24:42
That can be done like this:
console.log('dt = ' + dt.toString().replace(/\sGMT.*$/, ""));
Working demo: http://jsfiddle.net/jfriend00/hg5m0r1r/
If you want something different to show, then you should construct the string representation you want yourself rather than letting the system automatically call .toString(). You can look at the Date object methods available and decide what you want to display. A Date object internally is a number of ms since the epoch time so any string representation is a conversion of some kind. You have to tell it what conversion you want.
You can see a list of the many date methods here.

How to work with a Javascript +Date() numeric time stamp in Python?

I've a JavaScript date string which I want to convert in understandable form. E.g.
new Date(1415988000000)
which gives the output
Fri Nov 14 2014 23:30:00 GMT+0530 (IST)
I want to do this in python. I don't want to use PyV8. Is there any other alternative ?
You don't need to write Javascript in Python to convert the timestamps.
The following works in pure python.
Note:
The JS Date format is the number of milliseconds since Jan 1,1970 UTC.
Oddly enough, the python format for time.time() is the number of seconds since Jan 1, 1970 UTC.
This standard is sometimes called Unix time
First, for the milliseconds to seconds time conversion, you need to divide 1415988000000 by 1000, obtaining 1415988000
Then you can use the datetime library like this:
import datetime
d = datetime.datetime.fromtimestamp(1415988000)
print d
Obtaining:
2014-11-14 13:00:00
This print seems to have converted d to my TZ which is UTC-5.
So UTC time would be 18:00.
This explains the later time, 23:30, you receive in JS for the same stamp in IST or UTC+5:30

How can I compare two different date formats and different time zones in JavaScript?

I want to compare two different time objects given in different formats and time zones.
Input as structured english:
IF "Mon Sep 15 2014 18:20:52 GMT+0200 (CEST)" is greater than "2014-09-04T13:57:33.338Z"
Expected output:
True
How to achieve this in JavaScript?
Native JavaScript
You can use the Date.parse(dateObject) to convert your date to a Unix timestamp and do your test on it. You can look at the documentation about it.
Using an additionnal library
You can also use an external library, such as Moment.js. This library allows you to compare your date without transforming them into timestamps or other exoctic formats.
You just have to get your date and compare it to another one:
moment("Mon Sep 15 2014 18:20:52 GMT+0200 (CEST)").isAfter('2014-09-04T13:57:33.338');
I let you explore this wonderful library by yourself if you want.
Moment website: http://momentjs.com/
Hope this two solutions will help you :)
In JavaScript use Date.parse(myDateObject) to convert different date formats to a Unix timestamp (although the resulting last 3 digits are not part of the unix timestamp, but are milliseconds).
e.g.:
if (Date.parse("Mon Sep 15 2014 18:20:52 GMT+0200 (CEST)") > Date.parse("2014-09-04T13:57:33.338Z")) {}; // evaluates to true
Do not expect the Date object to correctly or consistently parse date and time strings. There are a number of libraries to help if you have many different formats to support, but if you only have one or two then supporting them is not hard.
To parse an UTC ISO 8601 format string like '2014-09-04T13:57:33.338Z':
function parseISOUTC(s) {
// Get the parts
var b = s.split(/\D+/);
// Return a new Date
return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5], b[6]));
}
To parse a string like 'Mon Sep 15 2014 18:20:52 GMT+0200 (CEST)' takes a little more work:
function parseMDYHMSO(s) {
// Get the parts
var b = s.split(/[ :]/);
// Convert the month name to a number
var months = {jan:0,feb:1,mar:2,apr:3,may:4,jun:5,
jul:6,aug:7,sep:8,oct:9,nov:10,dec:11};
var month = months[b[1].toLowerCase()];
// Get the offset
var sign = s.indexOf('+') == -1? 1 : -1;
var offset = b[7].substr(4,2) * 60;
offset += +b[7].substr(6,2);
// Create a new Date
return new Date(Date.UTC(b[3], month, b[2], b[4], +b[5] + sign*offset, b[6]));
}
So now you have two date objects. If you want to compare just the time part, then get the hours, minutes and seconds of each and compare them:
var d0 = parseISOUTC('2014-09-04T13:57:33.338Z');
// 2014-09-15T16:20:52.000Z
var d1 = parseMDYHMSO('Mon Sep 15 2014 18:20:52 GMT+0200 (CEST)');
d0.getUTCHour(); // 13
d1.getUTCHour(); // 16
d0.getUTCMin(); // 57
d1.getUTCMin(); // 20
d0.getUTCMin(); // 33
d1.getUTCMin(); // 52
You can also just use the plain getHour, getMinute, etc. methods but the UTC ones make it clear that you're using the same offset.
You can also do the above just using the time part with offset and ignore the date. Convert the hours, minutes and seconds to say seconds, apply the offset, allow for day boundaries and compare the result.

ANSI date (COBOL Integer date) to current date

I need to translate an integer representing the number of days since 01.01.1601 (as of 6th November 2012: 150422) to a javascript Date object.
Each year has approximately 365.242199 days, so the calculation should be as follows:
var daysPerYear = 365.242199;
var daysSince = 150422;
var year = 1601 + Math.floor(daysSince / daysPerYear); // correct, gives me 2012
var days = Math.floor(daysSince % daysPerYear); // wrong, gives me 307
Now I create the Date object:
var date = new Date(year, 0);
date.setDate(days);
The date now points to 'Fri Nov 02 2012 00:00:00 GMT+0100 (CET)' which is off by about 4 days.
What is wrong with my calculation? Is there an easier way to obtain the Date object?
Clone out a copy of OpenCOBOL 1.1, and look through libcob/intrinsic.c for computations.
See cob_intr_date_of_integer in particular.
For an SVN readonly checkout
svn checkout svn://svn.code.sf.net/p/open-cobol/code/trunk open-cobol-code
or browse to
http://sourceforge.net/projects/open-cobol/files/open-cobol/1.1/open-cobol-1.1.tar.gz/download
JavaScript dates revolve from midnight on 1st January, 1970. If you do new Data().getTime(), for example, you'll be returned the number of milliseconds from that point. Therefore, to convert your dates from 1st January, 1601, you need to calculate the exact number of milliseconds between 1/1/1601 and 1/1/1970 and take the difference from your date (also converted into milliseconds).
This way, all you are doing is adding numbers together and won't suffer from any floating point inaccuracies or error from your approximations.

Categories