Comparing 2 dates with momentJS - javascript

I am trying to compare a DAY/TIME e.g. Monday 09:00:00 with the current time to see if I am past that point in the week. e.g. If it is now 05:00:00 on Monday it should return true however it is returning false everytime
var dayTime = Moment("Wednesday 17:00:00", "dddd HH:mm:ss");
var now = Moment(Moment.now(), "dddd HH:mm:ss");
console.log(Moment.utc(dayTime).isBefore(now)); //returns false all the time
I found the following similar questions but it didn't seem to fix the issue after formatting the time.
Comparing two times with Moment JS
When I replace the moment.now() with a string such as "Wednesday 17:00:00" it returns the expected result.
Any idea what I need to do to moment.now() in order for this to work correctly?

Moment.now can be used as an extension point, but it's really not a public API. To get the current time in momentjs you just call moment(). Note that all moment calls use lowercase moment.
To see if your date and time is before the current time, you would just call:
moment('01/01/2016', 'MM/DD/YYYY').isBefore(moment())
You would replace the date and format in question with your own.
I see that you have a date format that includes only day of week and time. Moment will parse this, but be aware that the behavior might not be what you expect. When I parse your date, I get Wednesday December 30, 2015. Exactly what day this lands on will vary by locale. In any case, I doubt that it is what you want. If at all possible, I would get year, month, and day.
If you would like to instead set the moment to Wednesday this week, set the day on the moment using .day(). For instance:
moment().day(3).format()
"2016-06-15T20:19:55-05:00"

For anyone who is interested, the code I posted in my question was changing the day/hour but was setting the year to 2015 which meant that it was always in the past.
To fix I separated out the Day and the Hour and set to moment. Then compared that with now. e.g.
moment().set({"Day": "Friday", "Hour": "17"}).isBefore(moment())

Related

Javascript new date from month and year string

I bumped into a situation where I'm getting a string indicating only the month and year of a date, and I need to create a Date object out of it. If I pass just the string, e.g. "February 2020" into a Date constructor, I strangely get back the the day of the previous month, i.e. in this case 2020-31-01. Thus, I need to always add 1 day to get the proper month in the Date object.
Here is the code to replicate:
var date_str = "February 2020";
var dt = new Date(date_str)
console.log(dt) // Returns : 2020-01-31T23:00:00.000Z (????)
dt.setDate(dt.getDate() + 1);
console.log(dt) // Returns : 2020-02-01T23:00:00.000Z
Any idea what the logic is behind this rather strange behaviour, or do I miss something here?
Update
Have accepted the first answer as being relevant, thus the main question is solved. However, just to add to the confusion: the code snippet I included runs as described with node. Using EXACTLY the same logic in a Vue.js application return the correct Date. Very strange!
"February 2020" is not a valid input according to the specification thus you should not rely on it to work.
You should convert your input to one that is according to spec and then decide whether you need local time or UTC.
Handling time(zones) is one of the hardest things in JavaScript and I strongly recommend that you do not try to reinvent the wheel here yourself as it is really easy to mess up.
Libraries like momentjs can help you here.
Actually you are passing February 2020 into the date Constructor , and its assumes the
date as 1 February 2020 thus it give the output as its UTC date which may be previous
day depending on your region
Use moment.js library, it will give perfect.
moment("February 2020").format('L')
"02/01/2020"

Why .setHours(0,0,0,0) is resulting in T07:00:00.000Z

I need to get start of day and end of day. I have been reading that if I am going to do date stuff to use momentjs. While I might go that route right now I do not think I will need that much date manipulation so am gonna try to not add more npm packages to this project than needed. I was reading that you can set a date to start of day with .setHours(0,0,0,0) though when I try this in my terminal I am seeing the hours get set to T07:00:00.000Z can someone explain why? Feels like it should be T00:00:00.000Z
let date = new Date('2019-08-16T20:30:38Z');
date.setHours(0,0,0,0);
console.log(date);
I live in the Central timezone, UTC -5 this time of year, so I get T05:00:00.000Z when I run it. Since you live in the Pacific timezone (presumably), UTC -7, you get 7am UTC. You are setting the local time but outputting the time in UTC. From the documentation (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours):
The setHours() method sets the hours for a specified date according to local time, and returns the number of milliseconds since January 1, 1970 00:00:00 UTC until the time represented by the updated Date instance

Parsing the hour only

I'm using d3 v3 to parse some intraday data that has the following format:
time,value
09:00,1
09:05,2
09:10,3
...
So I set up a parsing variable like so:
var parseTime = d3.time.format("%H:%M").parse;
And I map the data within the scope of the csv call:
d3.csv("my_data.csv", function(error, rawData) {
var data = rawData.map(function(d) {
return {y_value: +d.value, date: parseTime(d.time)}
});
console.log(data)
}
In the console, I get something strange. Instead of only the hour, I get the full-fledged date, day of the week, month, even time zone.
data->
array[79]
0:Object->
date: Mon Jan 01 1900 09:00:00 GMT+0000
y_value: 1
Do dates need to be this complete? I suppose that could explain why I wound up with monday Jan. 1st, seems like a default of sorts. However, according to d3 time documentation, "%H:%M" is used for hours and minutes. And I could have sworn I did that much correct.
I know something is not quite right because my line graph is throwing the error:
error: <path> attribute d: expected number "MNaN"
My best guess is that the date is over-specified and the axis() is expecting an hour format.
My Question is: Why isn't my data being parsed as hour only? Should I change this from the parsing end? If that's not an option, can I have the x domain read a portion of the date (the hour and minute portion)?
Update: Here is a minimal block for further illustration of my plight.
When you say...
why isn't my data being parsed as hour only?
... it becomes evident that there is a basic misunderstanding here. Let's clarify it.
What is a date?
Simply put, a date is a moment in time. It can be now, or two months ago, or the day my son was born, or next Christmas, or the moment Socrates drank the hemlock. It does'n matter. What is important to understand is that all those dates have a century, a decade, a year, a month, a day, an hour, a minute, a second, a millisecond etc... (of course, those names are conventions that can be changed).
Therefore, it makes little sense having a date with just the hour, or just the hour and the minute.
Parsing and formating
When you parse a string, you create a date object. As we explained above, that date object corresponds to a moment in time, and it will have year, month, hour, timezone etc... If the string itself lacks some information, as year for instance, it will default to some value.
Look at this demo, we will parse a string into a date object, using the correct specifier:
var string = "09:00";
var parser = d3.timeParse("%H:%M");
var date = parser(string);
console.log("The date object is: " + date);
<script src="https://d3js.org/d3.v4.min.js"></script>
As you can see, we have a date object now. By the way, you can see that it defaults to a given year (1900), a given month (January), and so on...
However, in your chart, you don't need to show the entire object, that is, all the information regarding that moment in time. You can show just hour and minute, for instance. We will format that date.
Have a look:
var string = "09:00";
var parser = d3.timeParse("%H:%M");
var format = d3.timeFormat("%H:%M");
var date = parser(string);
console.log("The date object is: " + date);
console.log("The formatted date is: " + format(date));
<script src="https://d3js.org/d3.v4.min.js"></script>
That formatted date is useful for creating axes, tooltips, texts etc..., that is, showing the date you have without showing all its details. You can choose what information you want to show to the user (just the year, or just the month, or maybe day-month-year, whatever).
That's the difference between parsing and formatting.
Why using a formatter?
To finalise, you may ask: why am I using a formatter, if I will end up having the same thing I had at the beginning?
The answer is: you don't have the same thing. Now you have a date, not a string. And, using a date with a time scale, you can accomodate daylight savings, leap years, February with only 28 days, that is, a bunch of things that are impossible to do with a simple string.
PS: The demos above use D3 v4.
EDIT: After your update we can easily see the problem with your code: you have to pass an array to range().
var xScale = d3.time.scale().range([0,width]);
Here is the updated bl.ocks: http://bl.ocks.org/anonymous/a05e15339f7792f175d2bcebccf6bbed/7f23db481f1308eb0d5a1834f7cbc0b17d948167

momentjs days difference between two GMT dates

I'm trying to get difference of days between two GMT dates using moment
but I couldn't find it.
I'm on IST(+05:30) and I have some GMT dates(-05:00) in db,
I tried using following command
temp2.diff(temp1, "days")
here is a screenshot of all the commands tried in console
there we can clears see that dates are different and still shows the difference is 0
here is how I'm initializing moment objects of 'America/New_York'
var temp1 = moment.tz(new Date('Mon Jan 25 2016 22:00:00 GMT-0600'), 'America/New_York');
var temp2 = moment.tz(new Date('Tue Jan 26 2016 00:00:00 GMT-0600'), 'America/New_York');
any help appreaciated, thanks.
Well, there is less than 24 hours difference between those dates, so it's correct. The documentation says:
By default, moment#diff will return number rounded down. If you want the floating point number, pass true as the third argument.
> temp2.diff(temp1, "days", true)
0.08333333333333333
If you don't care about the hours at all, set them to 0 before you do the comparison
> temp2.hours(0).diff(temp1.hours(0), "days")
1
A few things:
You say that you are retrieving these values from a database, but then you show us loading them via the Date constructor from a string value. If you are really storing a string in your database, especially in that particular format, then you have much larger problems than the one you asked about! Please show us precisely how you load the values from your database to begin with.
You shouldn't rely on the Date object for parsing, especially when you are already using moment, which has much better parsing routines of its own.
You said these values where in America/New_York, but then you show an offset of -0600. That's never used in that time zone. The offset for the value you showed would be -0500.
You also said "I have some GMT dates(-05:00)" - which doesn't make any sense. GMT is +00:00. GMT-0500 means "5 hours behind GMT". Thus, you no longer have a "GMT date".
Be aware that the JavaScript Date object can only use the time zone of where the code is running. You cannot run it in any other time zone.
While Felix is correct in how you can show decimals with the diff function, you should realize that diff is giving you the actual elapsed time between the two moments in time you asked about. However, you seem to be wanting to know the total number of calendar days separating the two days that the moments fall into within the named time zone. To do that, you'd need to ignore the time portion. Using startOf('day') is an easy way to do that. Consider:
var a = moment.parseZone("2016-01-25T23:00:00-05:00");
var b = moment.parseZone("2016-01-26T01:00:00-05:00");
b.diff(a, 'days', true) // 0.08333333333333333 (not what you want)
b.startOf('day').diff(a.startOf('day'), 'days') // 1 (that's better!)
moment(b).startOf('day').diff(moment(a).startOf('day'),'days') // 1 (best approach)
Note a few things with this code:
The code in the last line is the best approach, as it leaves the original values of a and b alone. Otherwise, they would be modified. (Moments are mutable.)
You seem to already have the correct local time and offset, and thus there's no need to use moment-timezone's tz function. You can just use parseZone. Of course if this was just a side effect of your example, then you could still use moment-timezone, but I'd strongly recommend against using the Date constructor still.

Moment Js Issue : isoWeekYear & isoWeek method behavior

I fetched the iso week from a date by using moment's isoWeek function.
moment(new Date(2015,11,28)).isoWeek() //output 53
I fetched the iso week year from the same date by using moment's isoWeekYear function.
moment(new Date(2015,11,28)).isoWeekYear() //output 2015
But when I gave the same outputs to the input of moment function it results a different date.
moment().isoWeek(53).isoWeekYear(2015).isoWeekday(0).toDate() //output Dec 28 2014
For other dates it is working correctly. Is there anything that I am missing in my code or it is a bug with Moment ?
here is a demo JSFiddle console.log("Iso Week :",moment(new Date(2015,11,28)).isoWeek());
console.log("Iso Year :",moment(new Date(2015,11,28)).isoWeekYear());
console.log("Date :", moment().isoWeek(53).isoWeekYear(2015).isoWeekday(0).toDate());
It might be the order you've given to the segments.
This works:
moment().isoWeekYear(2015).isoWeekday(1).isoWeek(53).toDate());
Check this out from Moment.js docs.
if you chain multiple actions to construct a date, you should start
from a year, then a month, then a day etc. Otherwise you may get
unexpected results, like when day=31 and current month has only 30
days (the same applies to native JavaScript Date manipulation), the
returned date will be 1st of the following month.
Also isoWeekDays go from 1 to 7. By setting 0 you were getting next week's Monday.
first you have to understand one thing.in your first operation whats happening here is,
moment(new Date(2015,11,28)).isoWeek() //output 53
while creating date using new Date() you have passed 11 as month.so what will happen is while creating date month will get incremented by 1.so the date will be 2015-12-28.so the week number is 53.
so for the 3rd operation you have passed the same result.so moment returned the correct date.
in your case if you want to pass month subtract that by 1 in your 1st operation.
moment(new Date(2015,10,28)).isoWeek();
now you will get the correct answer

Categories