Comparing two dates in different timezones - javascript

I'm comparing two dates; one returned as a UTC String (as part of an Ajax response) and the second in local browser time:
Basically, I want to see if the date returned (endTime) happened before right now. My code is below and I thought I had it right but it's not working.
var isActive = true;
var buffer = 30000; // 30 seconds
var endTime = new Date(Date.parse(response.endTime)); // Fri Oct 23 2015 12:01:14 GMT-0400 (EDT)
var now = new Date(); // Thu Oct 22 2015 20:01:31 GMT-0400 (EDT)
var nowUtc = new Date(now).toUTCString(); // "Fri, 23 Oct 2015 00:01:31 GMT"
var nowTimeMs = new Date(nowUtc).getTime(); // 1445558491000
var endTimeMs = endTime.getTime() + buffer; // 1445616104000
if( nowTimeMs > endTimeMs ){
isActive = false;
}
isActive should remain as true but instead it's false. I feel like I've been looking at this too long and am missing something very simple. Am I?
Thanks for any helpful tips.
Update:
Based on the responses I thought I'd update my question. What is the best way to compare two dates where one is this:
new Date(); // Thu Oct 22 2015 21:51:53 GMT-0400 (EDT)
...and the other is a String representation of date:
"2015-10-23 01:49:27"
I figure the best way to create a valid Date object out of the String is using this code.
isThisActive:function(p){
var isActive = true;
var buffer = 30000;
var pEndTime = myObj.parseStringAsDate(p.callEndTime);
var now = new Date();
var offset = now.getTimezoneOffset() * 60000;
now.setTime( now.getTime() + offset );
var nowTimeMs = now.getTime();
var endTimeMs = pEndTime.getTime() + buffer;
if( nowTimeMs > endTimeMs ){
isActive = false;
}
return isActive;
},
parseStringAsDate:function(str){
var dateTimeStr = str.split(" ");
var dateStr = dateTimeStr[0].split("-");
var year = dateStr[0];
var month = dateStr[1];
var day = dateStr[2];
var timeStr = dateTimeStr[1].split(":");
var hours = timeStr[0];
var minutes = timeStr[1];
var seconds = timeStr[2];
return new Date( year,month,day,hours,minutes,seconds);
}
Because "pEndTime" is in UTC I applied the offset to the "now" Date object but even this is not working. Where's the problem here? I thought this would solve it.
SOLVED:
The latest code I posted did work. I was just getting incorrect values for the response.endTime (It wasn't converted to correct military time). Thank you everyone for your input. I've tried to upgrade as many helpful responses as I could.

You should not use the Date constructor or Date.parse (which do the same thing) to parse date strings. Either write your own parse function (below) or use a well maintained library.
To parse the format in the OP, you can use:
// Parse Thu Oct 22 2015 20:01:31 GMT-0400 (EDT)
function parseMMMDY(s) {
var b = s.split(/\W/);
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 sign = /GMT-\d{4}/i.test(s)? 1 : -1;
var min = +b[5] + (sign * b[8].slice(0,2) * 60 ) + (sign * b[8].slice(-2));
return new Date(Date.UTC(b[3], months[b[1].toLowerCase().slice(0,3)], b[2], b[4], min, b[6]));
}
document.write(parseMMMDY('Thu Oct 22 2015 20:01:31 GMT-0400 (EDT)'));

I think the problem is here:
var endTime = new Date(Date.parse(response.endTime));
respnonse.endTime is UTC, right? But when you parse it to Date value, Date.parse assumes it is in local timezone (GMT-0400 as in your example code). It means that the endDate gets the wrong value

I usually use moment.js in my projects which related to formatting date time, especially in the reports (I'm working in the field of finance). You must have one more library in your project but it provides many other functionalities
Sorry, this is for your new update. I haven't got enough 'population' to leave a comment :P

var endTime = new Date(Date.parse(response.endTime)); // Fri Oct 23 2015 12:01:14 GMT-0400 (EDT)
var now = new Date(); // Thu Oct 22 2015 20:01:31 GMT-0400 (EDT)
Your endTime doesn't seem to return a UTC date as you mentioned. It looks to be using (EDT) so maybe you didn't have to convert it to UTC.

Related

How Can I use new Date().setHours(0,0,0) in a single line? [duplicate]

What is the simplest way to obtain an instance of new Date() but set the time at midnight?
The setHours method can take optional minutes, seconds and ms arguments, for example:
var d = new Date();
d.setHours(0,0,0,0);
That will set the time to 00:00:00.000 of your current timezone, if you want to work in UTC time, you can use the setUTCHours method.
Just wanted to clarify that the snippet from accepted answer gives the nearest midnight in the past:
var d = new Date();
d.setHours(0,0,0,0); // last midnight
If you want to get the nearest midnight in future, use the following code:
var d = new Date();
d.setHours(24,0,0,0); // next midnight
A one-liner for object configs:
new Date(new Date().setHours(0,0,0,0));
When creating an element:
dateFieldConfig = {
name: "mydate",
value: new Date(new Date().setHours(0, 0, 0, 0)),
}
Just going to add this here because I landed on this page looking for how to do this in moment.js and others may do too.
[Rationale: the word "moment" already appears elsewhere on this page so search engines direct here, and moment.js is widespread enough to warrant to being covered going on how often it is mentioned in other date-related SO questions]
So, in version 2.0.0 and above:
date.startOf('day');
For earlier versions:
date.sod();
Docs:
http://momentjs.com/docs/#/manipulating/start-of/
You can probably use
new Date().setUTCHours(0,0,0,0)
if you need the value only once.
If calculating with dates summertime will cause often 1 hour more or one hour less than midnight (CEST). This causes 1 day difference when dates return. So the dates have to round to the nearest midnight. So the code will be (thanks to jamisOn):
var d = new Date();
if(d.getHours() < 12) {
d.setHours(0,0,0,0); // previous midnight day
} else {
d.setHours(24,0,0,0); // next midnight day
}
Adding usefulness to #Dan's example, I had the need to find the next midday or midnight.
var d = new Date();
if(d.getHours() < 12) {
d.setHours(12,0,0,0); // next midnight/midday is midday
} else {
d.setHours(24,0,0,0); // next midnight/midday is midnight
}
This allowed me to set a frequency cap for an event, only allowing it to happen once in the morning and once in the afternoon for any visitor to my site. The date captured was used to set the expiration of the cookie.
I have made a couple prototypes to handle this for me.
// This is a safety check to make sure the prototype is not already defined.
Function.prototype.method = function (name, func) {
if (!this.prototype[name]) {
this.prototype[name] = func;
return this;
}
};
Date.method('endOfDay', function () {
var date = new Date(this);
date.setHours(23, 59, 59, 999);
return date;
});
Date.method('startOfDay', function () {
var date = new Date(this);
date.setHours(0, 0, 0, 0);
return date;
});
if you dont want the saftey check, then you can just use
Date.prototype.startOfDay = function(){
/*Method body here*/
};
Example usage:
var date = new Date($.now()); // $.now() requires jQuery
console.log('startOfDay: ' + date.startOfDay());
console.log('endOfDay: ' + date.endOfDay());
In case you already have d3.js as a dependency in your project, or don't mind bringing it in, d3-time (d3.js library is modular as of v4.0.0) has got Intervals.
They might prove useful when setting dates to "default" values, e.g. midnight, 0.00 seconds, the first of the month, etc.
var d = new Date(); // Wed Aug 02 2017 15:01:07 GMT+0200 (CEST)
d3.timeHour(d) // Wed Aug 02 2017 00:00:00 GMT+0200 (CEST)
d3.timeMonth(d) // Tue Aug 01 2017 00:00:00 GMT+0200 (CEST)
Using the dayjs library, you can use the startOf('day') method.
const dayjs = require('dayjs');
const todayAtMidnight= dayjs().startOf('day');
// Get as a native date object
console.log(todayAtMidnight.toDate());
To get the start of a particular day you can use the following:
const date = dayjs("2023-02-12").startOf('day');

How to I get current time from angular material Date picker?

I am using angular material datepicker
https://material.angular.io/components/select/overview
but this returns only the date and not the current time :
Mon May 28 2018 00:00:00 GMT+0530 (IST)
Is there any way I can get the current time also from this?
You can use the ngModelChange to parse the date before setting it to your model, I recommend you momentJS for easy date manipulations.
in the HTML
<input [ngModel]="date" (ngModelChange)="onDataChange($event)" matInput [matDatepicker]="picker" placeholder="Choose a date">
In your Component.ts
onDataChange(newdate) {
const _ = moment();
const date = moment(newdate).add({hours: _.hour(), minutes:_.minute() , seconds:_.second()})
this.date = date.toDate();
console.log({hours: _.hour(), minutes:_.minute() , seconds:_.second()})
}
you can find the full solution here https://stackblitz.com/edit/angular-ecq2lc
Right now the material date picker provides just the current date (without the current time), but there is an open issue in the official repo, so we might see a time picker in the near future.
The angular material is not providing Time right now you need to manually get time from timeStamp, Try this -
function getTimeFromDate(timestamp) {
let date = new Date(timestamp * 1000);
let hours = date.getHours();
let minutes = date.getMinutes();
let seconds = date.getSeconds();
return hours+":"+minutes+":"+seconds
}
let timeStamp = new Date("Mon May 28 2018 00:00:00 GMT+0530 (IST)")
console.log(getTimeFromDate(timeStamp));
For Example currenttime = Mon May 28 2018 00:00:00 GMT+0530 (IST)
Currenttime is an example if u using current date means just use new Date()
//Sample function calling Method
Exacttime(){
this.functionName = this.diffhours(new(currenttime))
}
diffhours(currenttime){
var diff = new Date(currenttime);
diff .getHours(); // => 9
diff .getMinutes(); // => 30
diff .getSeconds(); // => 51
}

JS Check if multiple dates are within range

I have the following code where I have an arrival date and departure date and edit their format, as well as a disabled date:
var aankomstDatum = "19-05-2018";
var parts = aankomstDatum.split('-');
aankomstDatumDate = new Date(parts[2],parts[1]-1,parts[0]);
vertrekDatum = "02-06-2018";
var parts2 = vertrekDatum.split('-');
vertrekDatumDate = new Date(parts2[2],parts2[1]-1,parts2[0]);
var aankomstDatumDateCheck = (aankomstDatumDate.getMonth() + 1) + '/' + aankomstDatumDate.getDate() + '/' + aankomstDatumDate.getFullYear();
//alert(aankomstDatumDateCheck);
var vertrekDatumDateCheck = (vertrekDatumDate.getMonth() + 1) + '/' + vertrekDatumDate.getDate() + '/' + vertrekDatumDate.getFullYear();
//alert(vertrekDatumDateCheck);
var disabledDates = "26-05-2018";
var partsdisabled = disabledDates.split('-');
var disableddatesDatumDate = new Date(partsdisabled[2], partsdisabled[1]-1, partsdisabled[0]); //alert(disableddatesDatumDate);
var disableddatesDatumDateCheck = (disableddatesDatumDate.getMonth() + 1) + '/' + disableddatesDatumDate.getDate() + '/' + disableddatesDatumDate.getFullYear();
//alert(disableddatesDatumDateCheck);
if(dateCheck(aankomstDatumDateCheck,vertrekDatumDateCheck,disableddatesDatumDateCheck)) {
console.log("Not available");
} else {
console.log("Available");
}
function dateCheck() {
return true;
}
Basically, if the disabled date is between the arrival date and departure date, the if-else fires, and in the other case the else.
This code works (hooray!), but I'm not there yet. Because I planned to have multiple dates as var disabledDates and that's where I'm stuck. So, how can edit the code that multiple disabled dates are checked?
Here's a simplified version of your code, which works as you ask. I think it's better to construct Date objects using ISO8601 formatted text while testing i.e. "2018-05-19" (which creates dates in UTC). Also see tips at the end of the answer.
Click the Run code snippet button below the code to see the console output (much better than using alert):
var start = new Date("2018-05-19");
var end = new Date("2018-06-02");
var bookings = [
new Date("2018-05-26"),
new Date("2018-05-28")
];
if (validPeriod(start, end, bookings)) {
console.log("no bookings found");
} else {
console.log("found at least one booking");
}
function validPeriod(start, end, bookings) {
var valid = true;
for (var i = 0; i < bookings.length; i++) {
var date = bookings[i];
if (start <= date && date <= end) {
valid = false;
break;
}
}
return valid;
}
Tips
I strongly recommend you use Moment.js to work with dates. It'll save you headaches in the future.
If you don't opt for Moment.js, just remember that depending on how you create the date will depend on which timezone is used, and depending on the timezone of your computer which date will display, One easy way is to use the new Date(year, month, day, hours, minutes, seconds) constructor:
// for a browser/computer in timezone GMT+0200 (Paris)
// create a local date
new Date(2018, 5-1, 18).toString() // "Fri May 18 2018 00:00:00 GMT+0200 (CEST)"
new Date(2018, 5-1, 18).toISOString() // "2018-05-17T22:00:00.000Z"
// create a UTC date
new Date(Date.UTC(2018, 5-1, 18)).toString() // "Fri May 18 2018 02:00:00 GMT+0200 (CEST)"
new Date(Date.UTC(2018, 5-1, 18)).toISOString() // "2018-05-18T00:00:00.000Z"
// for a browser/computer in timezone GMT-0400 (New York)
// create a local date
new Date(2018, 5-1, 18).toString() // "Fri May 18 2018 00:00:00 GMT-0400 (EDT)"
new Date(2018, 5-1, 18).toISOString() // "2018-05-18T04:00:00.000Z"
// create a UTC date
new Date(Date.UTC(2018, 5-1, 18)).toString() // "Thu May 17 2018 20:00:00 GMT-0400 (EDT)"
new Date(Date.UTC(2018, 5-1, 18)).toISOString() // "2018-05-18T00:00:00.000Z"
But watch out if you use a string for the Date constructor because it uses Date.parse(dateString) internally and sometimes it's interpreted as a local date, and sometimes UTC:
// for a browser/computer in timezone GMT-0400 (New York)
new Date("08-19-2018"); // Sun Aug 19 2018 00:00:00 GMT-0400 (EDT) <-- local
new Date("08/19/2018"); // Sun Aug 19 2018 00:00:00 GMT-0400 (EDT) <-- local
new Date("2018-05-19"); // Fri May 18 2018 20:00:00 GMT-0400 (EDT) <-- UTC
new Date("2018/05/19"); // Sat May 19 2018 00:00:00 GMT-0400 (EDT) <-- local
Adding to the #djdavemark's answer,
You can also use JavaScript's in build some function to check if any date is falling in the given range.
As #RobG mentioned that for some browsers these date strings might give wrong results, therefore just to be safe you can explicitly format in the way Date constructor accepts.
From #CMS's answer Question: Why does Date.parse give incorrect results?
function parseDate(input) {
var parts = input.split('-');
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[2], parts[1]-1, parts[0]); // Note: months are 0-based
}
var startData = parseDate("19-05-2018")
var endDate = parseDate("25-05-2018")
var dateSet = [
"20-05-2018",
"21-05-2018",
"22-05-2018"
];
var dateSet2 = [
"26-05-2018",
];
function inBetween(element, index, array) {
return parseDate(element) >= startData && parseDate(element) <= endDate;
}
console.log(dateSet.some(inBetween))
console.log(dateSet2.some(inBetween))
This looks more elegant.
For more information on array's some method MDN Docs

converting date into timestamp

I have date like this 25. 02. 2014 18:48:21 and I'm trying to convert it into timestamp
var someDate = '25. 02. 2014 18:48:21';
var timestamp = new Date(someDate).getTime();
but it's returning NaN since I moved files to a new domain, what can be a problem?
'25. 02. 2014 18:48:21' is not a valid date format. You'll have to convert it with regex first, like that:
var someDate = '25. 02. 2014 18:48:21';
var converted = someDate.replace(/^(\d{2}\. )(\d{2}\. )(\d{4})/, '$3. $2$1');
// converted is in format: YYYY. MM. DD.
var timestamp = new Date(converted).getTime();
Running this within the console, creating a new date with that variable gives me Invalid Date. Trying switching around the 25. and 02. like so:
var someDate = '02. 25. 2014 18:48:21';
var timestamp = new Date(someDate).getTime(); // 1393372101000
The format should be "Month, Day, Year, Time".
Switching month and day will work. I also removed the dots.
var date = "25. 02. 2014 18:48:21";
new Date(date.replace(/(\d{2})\. (\d{2})\./, '$2 $1'))
// Tue Feb 25 2014 18:48:21 GMT+0100 (W. Europe Standard Time)
you can try something like below (if your string has always same format)
var someDate = '25. 02. 2014 18:48:21';
var arr = someDate.split(' ');
var time = arr[3].split(':');
var timeStamp = new Date(arr[2],arr[1].split('.')[0],arr[0].split('.')[0],time [0],time[1],time[2]).getTime();
It uses javascript date object constructor
var d = new Date(year, month, day, hour, minute, seconds);
which works across all browsers
function convertSomeDate(str){
var d= str.match(/\d+/g),
dA= [d[2], '-', d[1], '-', d[0], 'T', d[3], ':', d[4], ':', d[5], 'Z'].join('');
return +new Date(dA)
}
var someDate= '25. 02. 2014 18:48:21';
convertSomeDate(someDate)
/* returned value: (Number)
1393354101000
*/

convert custom date string to date object

How can I convert a string representation of a date to a real javascript date object?
the date has the following format
E MMM dd HH:mm:ss Z yyyy
e.g.
Sat Jun 30 00:00:00 CEST 2012
Thanks in advance
EDIT:
My working solution is based on the accepted answer. To get it work in IE8, you have to replace the month part (e.g. Jun) with the months number (e.g. 5 for June, because January is 0)
Your date string can mostly be parsed as is but CEST isn't a valid time zone in ISO 8601, so you'll have to manually replace it with +0200.
A simple solution thus might be :
var str = "Sat Jun 30 00:00:00 CEST 2012";
str = str.replace(/CEST/, '+0200');
var date = new Date(str);
If you want to support other time zones defined by their names, you'll have to find their possible values and the relevant offset. You can register them in a map :
var replacements = {
"ACDT": "+1030",
"CEST": "+0200",
...
};
for (var key in replacements) str = str.replace(key, replacements[key]);
var date = new Date(str);
This might be a good list of time zone abbreviation.
You can use following code to convert string into datetime:
var sDate = "01/09/2013 01:10:59";
var dateArray = sDate.split('/');
var day = dateArray[1];
// Attention! JavaScript consider months in the range 0 - 11
var month = dateArray[0] - 1;
var year = dateArray[2].split(' ')[0];
var hour = (dateArray[2].split(' ')[1]).split(':')[0];
var minute = (dateArray[2].split(' ')[1]).split(':')[1];
var objDt = new Date(year, month, day, hour, minute);
alert(objDt);

Categories