Check if time is the same with Moment.js - javascript

How to check if time is the same for Moment objects with different dates?
For example I have object like
const endDate = moment().add(30, 'days').endOf('day');
and I want to check if some moment object is endOf day.
private isEndOfDay(dateTime: string) {
const m = moment().endOf('day');
return m.isSame(dateTime, 'minute');
}
const receivedDateFormat: string = 'YYYY-MM-DD hh:mm:ss';
this.isEndOfDay(this.endDate.format(this.receivedDateFormat))
But for this case, when I pass "minute" parameter, it will check minute, hour, day, month and year... which isn't what I want to check.

The part of the documentation that explains that behaviour is
When including a second parameter, it will match all units equal or larger. Passing in month will check month and year. Passing in day will check day, month, and year.
So, if you just want to compare the minutes, you'll need to do something like
endDate.minute() === startDate.minute()
To compare the time only, format() the dates
endDate.format('HH:mm:ss') === startDate.format('HH:mm:ss')

To compare only time part you can set a given date (year, month and day) to your input.
Please note that passing 'minute' to isSame will ignore seconds.
Here a live sample:
function isEndOfDay(dateTime) {
let m = moment().endOf('day');
let m2 = moment(dateTime);
m2.set({
y: m.year(),
M: m.month(),
D: m.date()
});
return m.isSame(m2, 'minute');
}
var endDate = moment().add(30, 'days').endOf('day');
const receivedDateFormat = 'YYYY-MM-DD hh:mm:ss';
var ret = isEndOfDay(endDate.format(this.receivedDateFormat))
console.log(ret);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
Another way to to is checking only units that matter for you:
function isEndOfDay(dateTime) {
let m = moment().endOf('day');
let m2 = moment(dateTime);
if( m.hours() === m2.hours() &&
m.minutes() === m2.minutes() &&
m.seconds() === m2.seconds() ){
return true;
}
return false;
}
var endDate = moment().add(30, 'days').endOf('day');
const receivedDateFormat = 'YYYY-MM-DD hh:mm:ss';
var ret = isEndOfDay(endDate.format(this.receivedDateFormat))
console.log(ret);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
See Get + Set section of the docs to see how to get and set units of moment objects.

Related

First week of the year belongs in December?

I have a small method in js that looks like this:
const getSelectWeekText = (weekNumber, year) => {
let date = moment().year(year).week(weekNumber);
let month = date.format('MMMM');
return `Week ${weekNumber} (${month})`;
};
Running example here:
https://jsfiddle.net/472uoLg8/
I dont understand why the first item in the result has Month of December? I expected it to be January.
Because different locales define week of year numbering differently, Moment.js added moment#week to get/set the localized week of the year.
Use moment().isoWeek(weekNumber);
const getSelectWeekText = (weekNumber, year) => {
let date = moment().year(year).isoWeek(weekNumber);
let month = date.format('MMMM');
return `Week ${weekNumber} (${month})`;
};
Refer to https://momentjs.com/docs/#/get-set/week/.

Comparing two dates in when one date is in a previous year

I have this function that determines if two sets of dates are overlapping. When the set of dates are in the same year, it works correctly and returns true if there's overlap. If one of the dates is from a previous year, the comparison fails to detect the overlap.
For instance:
var obj = { startDate1: "02/01/2020",
endDate1: "03/01/2020",
startDate2:"02/05/2020",
endDate2:"02/15/2020" }
Using:
if ((obj.endDate1 >= obj.startDate2 && obj.startDate1 <= obj.endDate2) ||
(obj.endDate2 >= obj.startDate1 && obj.startDate2 <= obj.endDate1)) {
}
Returns true since the dates overlap.
However, when startDate1 is in a different year (2019), like so:
var obj = { startDate1: "12/01/2019",
endDate1: "03/01/2020",
startDate2:"02/05/2020",
endDate2:"02/15/2020" }
The expression above fails to detect the overlap even though startDate1 and endDate1 do in fact overlap with startDate2 and endDate2.
I've tried using moment and regex to format the dates, but to no avail. Any ideas what I'm doing wrong?
Edit: Here's how I'm using moment:
const obj = {
startDate1: moment(new Date(value.startDate)).format("MM/DD/YYYY"),
endDate1: moment(new Date(value.endDate)).format("MM/DD/YYYY"),
startDate2: moment(new Date(startDate)).format("MM/DD/YYYY"),
endDate2: moment(new Date(endDate)).format("MM/DD/YYYY")
};
The values I'm passing in to new Date are iso date strings.
Sorry for the confusion..
Edit #2/Answer:
I just converted the dates using native JS Date.parse.
const obj = {
certStart: Date.parse(value.startDate),
certEnd: Date.parse(value.endDate),
startDate: Date.parse(startDate),
endDate: Date.parse(endDate) };
Using the Native Date function in js
var obj = {
startDate1: "02/01/2020",
endDate1: "03/01/2020",
startDate2:"02/05/2020",
endDate2:"02/15/2020"
};
// Create a clone of obj object and convert values to timestamp.
var $dates = {};
$dates.startDate1 = new Date(obj.startDate1).getTime();
$dates.startDate2 = new Date(obj.startDate2).getTime();
$dates.endDate1 = new Date(obj.endDate1).getTime();
$dates.endDate2 = new Date(obj.endDate2).getTime();
Comparing time:
if (($dates.endDate1 >= $dates.startDate2 && $dates.startDate1 <= $dates.endDate2) ||
($dates.endDate2 >= $dates.startDate1 && $dates.startDate2 <= $dates.endDate1)) {
// etc...
}
Use new Date() or moment.js to create and manipule dates.
var obj = { startDate1: moment("12/01/2019"),
endDate1: moment("03/01/2020"),
startDate2:moment("02/05/2020"),
endDate2:moment("02/15/2020")}
and moment functions to manipulate dates
Despite your tag, it doesn't seem like you are actually formatting the dates using momentjs - unless you aren't sharing some of the code. It really looks like you are making string comparisons. For date comparison in general, I suggest reading the related: Compare two dates with JavaScript
Relevant MDN on Date: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
And don't forget to reference the moment.js docs: https://momentjs.com/docs/
EDIT: As already pointed out, you are using .format(), which returns a display string https://momentjs.com/docs/#/displaying/format/ - so you're still comparing strings instead of dates.
You may want to checkout isBetween: https://momentjs.com/docs/#/query/is-between/
Parse date string to Date, then get its value as a number:
const [m, d, y] = dateStr.split('/').map(Number)
// month is 0-indexed, whereas year and day are 1-indexed
const dateVal = new Date(y, m - 1, d).valueOf()
Then, you can easily compare them with >, <, and so on.
If the date string is in YYYY/MM/DD format then the string comparison will work.
var obj = {
startDate1: "2019/12/01",
endDate1: "2020/03/01",
startDate2: "2020/02/05",
endDate2: "2020/02/15"
}
// this will work
if ((obj.endDate1 >= obj.startDate2 && obj.startDate1 <= obj.endDate2) ||
(obj.endDate2 >= obj.startDate1 && obj.startDate2 <= obj.endDate1)) {
console.log('overlap detected')
}

How to compare Current System date with with another date

I am getting date in string format from API.
End Date 2014-06-03T06:16:52. I need to write an if-else logic and compare the end date and current date.If end date is less than current date then show customer as In Active and if end date is greater than display the Customer as Active.
I have tried following logic but I am not able to understand and get today's time in string fromat.
this.endDate = this.sampleData != null ?
this.sampleData.customerStartDate : null;
this.currentDate = new Date();
var dd = this.currentDate.getDate();
var mm = this.currentDate.getMonth() + 1;
var yyyy = this.currentDate.getFullYear();
this.currentDate = new Date().toLocaleString()
console.log('End Date', this.endDate);
console.log('Current Date: ', this.currentDate);
if (this.endDate == null) {
this.customerStatus = 'Active';
} else {
this.customerStatus = 'In Active';
}
I am getting current date as Current Date: 4/2/2019, 1:23:34 AM
I want to be able to get in same format as End Date.
My main task is to compare the dates how do I achieve it ?
Ideally you want to clean up the date you're getting from an API, and convert it to a JS Date object. You can do this by keeping only the 2014-06-03T06:16:52 part, and giving it to the new Date() constructor.
You can get the current date by calling new Date() without parameters.
You can the turn the dates in to numbers by calling getTime() on each.
You can then compare the numbers.
const incoming_date = new Date('2014-06-03T06:16:52');
const current_date = new Date();
if (incoming_date.getTime() < current_date.getTime() {
// incoming_date is before current_date
} else {
// current_date is before incoming_date
}
as simple as this:
let date=new Date("2014-06-03T06:16:52")
date>new Date()
you could try to express dates in ms since the Unix Epoch with getTime() and compare them
if (currDate.getTime() > endDate.getTime()) {
// set customer to inactive
} else {
// keep customer active
}
I personally like to use moment() for javascript dates. You really just need to have it compare the same format, so you could have something like:
this.currentDate = moment().toISOString();
const dataDate = this.sampleData ? this.sampleData.customerStartDate : null;
this.endDate = moment(dataDate).toISOString();
if (this.endDate > this.currentDate) {
this.customerStatus = 'Active';
} else {
this.customerStatus = 'Inactive';
}

Showing next available dates with 24h margin with Angular and MomentJS

I'm trying to display an array of possible delivery dates using AngularJS and MomentJS.
The issue is that it needs to meet certain conditions: Delivery dates are only Monday, Wednesday and Fridays.
Also, when the page loads, it recognizes the current date and it will only display the next available date that is minimum 24h away (e.g., if I load the page on a Sunday at 1pm, the first available date will be Wednesday, as Monday doesn't meet the 24h margin).
So far I could only think if dealing with the issue doing conditionals for every day of the week, but I'm pretty sure there has to be a neater way of dealing with it.
Here's what I did so far:
$scope.today = moment();
$scope.$watch('today', function () {
if ($scope.today = moment().day('Sunday')){
$scope.nextdateone = moment().add(3, 'd');
$scope.nextdatetwo = moment().add(5, 'd');
$scope.nextdatethree = moment().add(8, 'd');
$scope.nextdatefour = moment().add(10, 'd');
}
else if ($scope.today = moment().day('Monday')){
$scope.nextdateone = moment().add(2, 'd');
$scope.nextdatetwo = moment().add(4, 'd');
$scope.nextdatethree = moment().add(7, 'd');
$scope.nextdatefour = moment().add(9, 'd');
}
else if ...
});
This was the logic I came up with, but it doesn't really work as of now...
Any tips?
The delivery dates "Monday, Wednesday and Fridays", which (according to http://momentjs.com/docs/#/get-set/day/) you can represent as 1, 3 and 5.
So I would create a array with those dates, and then given the current day I would iterate that array of delivery dates to find the most suitable one... something like this:
const deliveryDates = [1, 3, 5];
const getDeliveryDate = (today) => {
let deliveryIndex = -1;
deliveryDates.some((date, index) => {
// If today is a delivery date, then schedule for the next delivery
if (today === date) {
deliveryIndex = index + 1;
return true;
}
// If today is before the current delivery date, store it
if (today < date) {
deliveryIndex = index;
return true;
}
});
// If delivery date is out of bounds, return the first delivery date
return deliveryIndex === deliveryDates.length || deliveryIndex === -1 ? 0 : deliveryIndex;
};
const getNextDelivery = (today) => {
return deliveryDates[getDeliveryDate(today)];
};
console.log(moment().day(getNextDelivery(moment().day())));
You can check a working example here:
https://jsbin.com/jawexafiji/edit?js,console

How to create a new Date() in Javascript from a non-standard date format

I have a date in this format: dd.mm.yyyy
When I instantiate a JavaScript date with it, it gives me a NaN
In c# I can specify a date format, to say: here you have my string, it's in this format, please make a Datetime of it.
Is this possible in JavaScript too? If not, is there an easy way?
I would prefer not to use a substring for day, substring for month etc. because my method must also be capable of german, italian, english etc. dates.
You will need to create a function to extract the date parts and use them with the Date constructor.
Note that this constructor treats months as zero based numbers (0=Jan, 1=Feb, ..., 11=Dec).
For example:
function parseDate(input) {
var parts = input.match(/(\d+)/g);
// note parts[1]-1
return new Date(parts[2], parts[1]-1, parts[0]);
}
parseDate('31.05.2010');
// Mon May 31 2010 00:00:00
Edit: For handling a variable format you could do something like this:
function parseDate(input, format) {
format = format || 'yyyy-mm-dd'; // default format
var parts = input.match(/(\d+)/g),
i = 0, fmt = {};
// extract date-part indexes from the format
format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });
return new Date(parts[fmt['yyyy']], parts[fmt['mm']]-1, parts[fmt['dd']]);
}
parseDate('05.31.2010', 'mm.dd.yyyy');
parseDate('31.05.2010', 'dd.mm.yyyy');
parseDate('2010-05-31');
The above function accepts a format parameter, that should include the yyyy mm and dd placeholders, the separators are not really important, since only digits are captured by the RegExp.
You might also give a look to DateJS, a small library that makes date parsing painless...
It's easy enough to split the string into an array and pass the parts directly to the Date object:
var str = "01.01.2010";
var dmy = str.split(".");
var d = new Date(dmy[2], dmy[1] - 1, dmy[0]);
There is no built in way to manipulate dates the way you would like.
The jQuery-UI datepicker has the functionality you want, I'm sure many other libraries have something similar.
$.datepicker.parseDate('dd.mm.yy', '31.12.2007');
t="01.01.1970"
parts = t.split(".");
for(var i = 0; i < parts.length; i++) parts[i] = parseInt(parts[i], 10);
new Date(parts[2], parts[1]-1, parts[0]);
Date defined as (Year, Month, Date)
Date()'s month parameter takes Month in Zero based index. January = 0, february = 1, march = 2... etc
Parsing the string to an int isn't necessary, but I dislike passing strings into functions and just hoping that JavaScript will "get it"... Sort of like how some people prefer ===
Building on CMS answer, I created this function to deal with a variable format
function parseDate(input, format) {
format = format || 'yyyy-mm-dd'; // default format
//Change from PHP date format to JS
if (format == 'd/m/Y') {
format = 'dd/mm/yyyy';
}
if (format == 'd/m/Y H:i:s') {
format = 'dd/mm/yyyy hh:ii:ss';
}
let date = NaN;
if (format == 'dd/mm/yyyy') {
let parts = input.match(/(\d+)/g),
i = 0, fmt = {};
// extract date-part indexes from the format
format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = parts[i++]; });
//create date for new format
let createdDate = new Date(fmt['yyyy'], fmt['mm']-1, fmt['dd']);
//check if dates are equal by comparing parts. The issue I had here was
//when I passed an invalid value for month, the output was adjustement to
//accomodate for the extra months
if (
createdDate.getFullYear() == fmt['yyyy'] &&
createdDate.getMonth() == (fmt['mm']-1) &&
createdDate.getDate() == fmt['dd']
) {
date = createdDate;
}
}
//same but taking into account hours minute and seccond
if (format == 'dd/mm/yyyy hh:ii:ss') {
let parts = input.match(/(\d+)/g),
i = 0, fmt = {};
// extract date-part indexes from the format
format.replace(/(yyyy|dd|mm|hh|ii|ss)/g,
function(part) { fmt[part] = parts[i++]; });
let createdDate = new Date(
fmt['yyyy'], fmt['mm']-1, fmt['dd'],
fmt['hh'], fmt['ii'], fmt['ss']
);
if (
createdDate.getFullYear() == fmt['yyyy'] &&
createdDate.getMonth() == (fmt['mm']-1) &&
createdDate.getDate() == fmt['dd'] &&
createdDate.getHours() == fmt['hh'] &&
createdDate.getMinutes() == fmt['ii'] &&
createdDate.getSeconds() == fmt['ss']
) {
date = createdDate;
}
}
return date;
}
Modified version of the accepted answer which supports value and format without 'dd' and uppercase format
function parseDate(input, format) {
format = (format || 'yyyy-mm-dd').toLowerCase(); // default format
var parts = input.match(/(\d+)/g),
i = 0, fmt = {};
// extract date-part indexes from the format
format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });
return new Date([parts[fmt['yyyy']], parts[fmt['mm']], parts[fmt['dd']]].filter(x => x !== undefined).join('-'));
}
parseDate('10/2018', 'MM/YYYY')

Categories