JavaScript loop through Json dates - javascript

I'm trying to use JavaScript to loop through a json file which has time periods (starting date/time and ending date/time), and check if now (current date time) falls between any time period in such list.
Following is my code, but can't get where I'm wrong. Any help?
<html>
<script type="text/javascript">
var data = {
"period": {
"startend": [{
"startDate": "2015-11-17 15:43:37",
"endDate": "2015-11-18 19:43:37"
}, {
"startDate": "2015-12-17 19:43:37",
"endDate": "2016-01-17 19:43:37"
}, {
"startDate": "2015-04-17 19:43:37",
"endDate": "2015-04-18 19:43:37"
}]
}
}
var periodArray = data.period.startend;
var curDate = new Date();
var datetime = curDate.getFullYear() + '-' + curDate.getMonth() + '-' + curDate.getDate() + ' ' + curDate.getHours() + ':' + curDate.getMinutes() + ':' + curDate.getSeconds();
for (i = 0; i < periodArray.length ; i++) {
var obj = periodArray[i]
if (datetime > obj.startDate && datetime < obj.endDate){
alert('Falls within period');
} else {
alert('Not within any period');
}
}
</script>

The basic idea is to convert the date strings to actual Date objects so they can be compared with the current date (new Date()). Let's begin by defining a helper function that when initialized, closes over the current date, producing a function that takes a start date and an end date, either in String or in Date form, and returns true if and only if the closed over current date is in the range.
Definition.
// () -> (([String|Date] * [String|Date]) -> Boolean)
// When initialized, closes over the current date and returns
// a predicate on String or Date objects.
function includesNow() {
var curDate = new Date();
return function(start, end) {
var startDate = (typeof start === "string")
? new Date(start) : start;
var endDate = (typeof end === "string")
? new Date(end) : end;
return (curDate > startDate) && (curDate < endDate);
};
}
Usage.
With the help of the helper function, we can then pretty easily filter the "current" dates:
// Get the list of (date string) objects.
var allDates = data.period.startend;
// Capture the current date, returning the date range comparator.
var comparator = includesNow();
// Get the list of those (date string) objects `obj`
// that satisfy `comparator(obj.startDate, obj.endDate) === true`.
var currentDates = allDates.filter(function(obj) {
return comparator(obj.startDate, obj.endDate);
});
// This is a function of current date, so will be empty at some point.
currentDates[0];
// => Object {startDate: "2015-11-17 15:43:37", endDate: "2015-11-18 19:43:37"}
If you know your objects will always be Strings and never actual Date objects, then you can simplify includesNow considerably. If you're interested in the closed range be sure to replace > and < with ≥ and ≤, respectively.

JSON date is not a date object. It's a string. You're trying to compare a Date obj to a String.
If the JSON date was an ISO formatted date you could do :
var dateStr = JSON.parse(date);
var realDate = new Date(dateStr);
realDate would now have a js date object. Unfortunately in your example the startDate and endDate are not ISO strings.
This would be the easiest/cleanest solution. Otherwise you could always get the JSON date strings and break them apart with substring() and convert the years/months/days with Number(); and then compare them that way?

Related

How can I get the timezone offset from string in javascript?

I have a string 2021-04-07T13:51:39.664+11:00 which I use to create a Date object: d = new Date('2021-04-07T13:51:39.664+03:00').
After that, d is an instance to represent the date time. Now I'd like to get the timezone offset from d, but d.getTimezoneOffset() always return local timezone offset which is -600 in my case. How can I get the timezone offset from the string? Does it get lost when I build the date instance? Do I have to parse the string to get it?
If I have a date object, how can I generate a string with the offset at the end: 2021-04-07T13:51:39.664+03:00? toISOString() only generate UTC time.
I know moment is a good date library but I don't want to add this dependency since it is too large.
function dateZ(dateString) {
var _date = dateString.substring(0, 23);
var _offset = dateString.substring(23);
var _dateValue = new Date(dateString);
function offset(value) {
if (value) {
_offset = value;
_dateValue = new Date(toString());
}
return _offset;
}
function date(value) {
if (value) {
_date = value;
_dateValue = new Date(toString());
}
return _dateValue;
}
function toString() {
return `${_date}${_offset}`
}
return { offset, date, toString };
}
var d = dateZ('2021-04-07T13:51:39.664+03:00');
console.log(d.date(), d.offset(), d.toString());
d.offset('+05:30');
console.log(d.date(), d.offset(), d.toString());
This is probably not the best possible approach, but it is portable and quite useful if you are in control of the application environment.
friendlyDate = function( x ){
var label = "Day Month Date Year Time Offset".split(" "),
d = x ? new Date(x) : new Date(),
s = ( d + "" ) .split( / / );
s.length = label.length;
for( var x in s )s[ label[ x ] ] = s[ x ];
s.length = 0;
return s
}
/**/
dte = friendlyDate();
for(var x in dte)console.log(x + ": "+ dte[x]);
p.s.: you might need to readjust\rearrange the labels for certain targeted browsers. [Not all browser vendor\version date string representations are returned equal ;)]
How to initialize a JavaScript Date to a particular time zone
There is no time zone or string format stored in the Date object itself.
Seems like either string parsing or a library (there are lighter-weight ones than moment if you're interested).

How to exclude weekends in date object in Javascript

I'm facing issue with excluding weekend dates in JavaScript.For my business requirement I want to exclude 3 days from date object Friday, Saturday and Sunday in every week.What I need here is the values of Friday should display as Monday, Saturday as Tuesday and Sunday as Wednesday. I'm able to do this.
The issue that I'm facing here is when we run the above example the a[0] value should be 21-SEP-2017 but I'm getting 20-SEP-2017 and remaining array values should not change. So please do help me out in resolving this issue
var a = ["21-SEP-2017", "22-SEP-2017", "23-SEP-2017", "24-SEP-2017", "25-SEP-2017"];
for (i = 0; i < a.length; i++) {
var startDate = a[i];
startDate = new Date(startDate.replace(/-/g, "/"));
var endDate = "",
noOfDaysToAdd = 1;
var count = 0;
endDate = new Date(startDate.setDate(startDate.getDate()));
if (startDate.getDay() != 0 && startDate.getDay() != 5 && startDate.getDay() != 6) {
endDate = new Date(startDate.setDate(startDate.getDate() + i - 1));
} else {
startDate.setDate(startDate.getDate() + 3)
endDate = new Date(startDate.setDate(startDate.getDate()));
}
console.log(endDate); //You can format this date as per your requirement
}
Your code seems not finished: the variables noOfDaysToAdd and count are never used, and if they were, they would be reset in every iteration of the loop, which cannot be the purpose.
That your output shows 20 September is because you did not output a stringified version of the date, but the date object itself, and then console.log will display the date as a UTC date (notice the time part matches the timezone difference). Instead use .toString() or another way to turn the date to a localised string.
Here is how you could do it:
function toDate(s) {
return new Date(s.replace(/-/g, '/'));
}
function toStr(dt) {
var months = ["JAN","FEB","MAR","APR","MAY","JUN",
"JUL","AUG","SEP","OCT","NOV","DEC"];
return [('0'+dt.getDate()).substr(-2), months[dt.getMonth()], dt.getFullYear()]
.join('-');
}
var a = ["21-SEP-2017", "22-SEP-2017", "23-SEP-2017", "24-SEP-2017", "25-SEP-2017"],
add = 0;
var result = a.map(toDate).map(dt => {
dt.setDate(dt.getDate()+add);
var move = [0, 6, 5].indexOf(dt.getDay()) + 1;
if (move) {
add += move;
dt.setDate(dt.getDate()+move);
}
return dt;
}).map(toStr);
console.log(result);

date object doesn't seem to be accurate when compared to today's date

I have this function that takes todays date and compares it to two weeks out. when it's less than or equal to the current date, it's supposed to add a class. However if it's today's date, it's not working. Otherwise it's working fine. Any ideas? Thanks
publicMethods.campaignEndDateAlert = function (dateString) {
if (!dateString) {
return dateString
};
var currentDate = new Date ();
var twoWeeks = new Date ();
twoWeeks.setDate(currentDate.getDate() + 14);
var inputDate = new Date(dateString);
// This is the part that doesn't seem to work - the first part of this if statement
if ((inputDate >= currentDate) && (inputDate <= twoWeeks)) {
dateString = '<span class="red">' + ax.Utils.RFCFormat(dateString, { excludeTime: true }) + '</span>';
} else {
dateString = ax.Utils.RFCFormat(dateString, { excludeTime: true })
};
return dateString;
};
Due to the information you provided:
You said that if it is today's date it doesn't work as expected. That is because new Date() will provide a date object with today's date and time. IF the value of dateString is something like "07-13-2017" without the time, you will need to strip the time out of the currentDate object if you expect inputDate >= currentDate to be true. Try using currentDate.setHours(0, 0, 0, 0); before comparing to inputDate.

setting UTC Date in javascript

I am creating a rotation schedule using fullcalendar. I need to create events that have start and end dates stored in UTC format. Regardless of how I am creating my dates, the dates are stored with a timezone. The dates will also have to be stored in a database. The test data I currently have in the database do not have a timezone and display correctly.
The user selects a start and end date using a datepicker but I add the time in the text box of the datepicker depending on the type of rotation the user has selected. So the initial start and end dates are from a text field. The format of these dates are like this:
start: 10/30/2015 12:00 AM
end: 11/19/2015 11:59 PM
I need to create a Date object in UTC format.
var startDate = convertTextToDate($('#schedule_start_date').val());
var endDate = convertTextToDate($('#schedule_end_date').val());
This is the convertTextToDate function:
function convertTextToDate(dateValue)
{
var dateArray = dateValue.split(/\D/);
var pm = /pm$/i.test(dateValue);
var hour = (+dateArray[3] || 0) % 12 + (pm ? 12 : 0);
var date = new Date(Date.UTC(dateArray[2], dateArray[0] - 1, dateArray[1], hour, +dateArray[4] || 0, +dateArray[5] || 0));
return date;
}
When I set a breakpoint at the return date; line, the date value always is shown with a timezone. When the events are created and displayed, the times are off by the timezone amount. The events are created using a while loop. So I have to add 7 days to each rotation. It creates the number of events expected but the start and end dates are off because, I believe, because it is not in UTC time.
This is the function to create the events:
$("#rotation_schedule_btn").click(function () {
//create member list order
var memberList = [];
$("#rotationList li").each(function () {
memberList.push({
id: $(this).attr('id'),
name: $(this).text(),
color: $(this).css('background-color')
})
});
var startDate = convertTextToDate($('#schedule_start_date').val());
var endDate = convertTextToDate($('#schedule_end_date').val());
//remove events between startDate & endDate
$('#edit_calendar').fullCalendar('removeEvents', function (event) {
if (event.start.toDate() >= startDate && event.start.toDate() <= endDate
|| event.end.toDate() >= startDate && event.end.toDate() <= endDate) {
return true;
}
});
//Create events from rotation schedule selected
var newEvents = [];
var rotation_length = $('#rotation_type_select option:selected').val();
var rotation_start_date = new Date(startDate.toUTCString());
var rotation_end_date = new Date(startDate.toUTCString());
//End date is to midnight
endDate.setMinutes(endDate.getMinutes() + 1);
rotation_end_date.setDate(rotation_end_date.getDate() + parseInt(rotation_length));
var member_index = 0;
while (rotation_end_date <= endDate)
{
var event = new Object();
event = {
title: memberList[member_index].name,
start: new Date(rotation_start_date.toUTCString()),
end: new Date(rotation_end_date.toUTCString()),
objectID: memberList[member_index].id,
color: memberList[member_index].color,
allDay: true,
textColor: 'white'
};
newEvents.push(event);
eventsAdded.push(event);
rotation_start_date.setDate(rotation_start_date.getDate() + parseInt(rotation_length));
rotation_end_date.setDate(rotation_end_date.getDate() + parseInt(rotation_length));
if ((memberList.length - 1) == member_index) {
member_index = 0;
}
else {
member_index++;
}
}
//Render events on calendar
$('#edit_calendar').fullCalendar('addEventSource', newEvents);
});
I need to create a Date object with no timezone, UTC format. Regardless of what I do, the date object is off by 4 hours, the time difference between UTC and my timezone.
I know I can display it in UTC format, but that is not what I need. I need to manipulate the date objects to create a events and they have to be in the UTC format.

Time conversion to ISO string is not correct with text field displayed

I have a text field in an MVC application that displays the date and time. The date is created using a datepicker and the time I add to the text field.
An example of the text is as follows:
10/23/2015 12:00 AM
I want to create a Date object with this time in ISO 8601 format. The date will be used to create an event in a fullcalendar jquery plugin.
When I try to create the Date object, the ISO string is:
2015-10-23T04:00:00.000Z
It should be 2015-10-23T00:00:00.000Z to represent midnight on that day.
This is my code:
<label id="schedule_start_date_lbl">Start Date: </label>
<input id="schedule_start_date" type="text" />
var startDayIndex = getDayIndex($('#rotation_start_time_txt').val());
$("#schedule_start_date").datepicker({
minDate: 0,
beforeShowDay: function (date) { return [date.getDay() == startDayIndex, ""] },
onSelect: function (dateText) {
$('#schedule_end_date').datepicker('option', 'minDate', dateText);
},
onClose: function (selectedDate) {
var rotation_txt = $('#rotation_start_time_txt').val();
var time = rotation_txt.substr(rotation_txt.indexOf(',') + 1);
$(this).val(selectedDate + time.toString(' HH:mm tt').toString());
}
});
$("#rotation_schedule_btn").click(function () {
//text value in schedule_start_date is: 10/23/2015 12:00 AM
var startDate = new Date($('#schedule_start_date').val()).toISOString();
//Value displayed is 2015-10-23T04:00:00.000Z
alert('startDate: ' + startDate);
});
Why is the time value off by 4 hours?
Thanks
UPDATE
I need to add to the Date objects after they are created. Creating the Date object using the function in the answer below is not creating it in UTC format. It can be displayed in that format but when I am creating events in the fullcalendar control, the date must be in UTC format and they are not.
This is my function to create a schedule:
$("#rotation_schedule_btn").click(function () {
//create member list order
var memberList = [];
$("#rotationList li").each(function () {
memberList.push({
id: $(this).attr('id'),
name: $(this).text(),
color: $(this).css('background-color')
})
});
//start and end date and time for new schedule
var startDate = convertTextToDate($('#schedule_start_date').val())
var endDate = convertTextToDate($('#schedule_end_date').val());
//remove events between startDate & endDate
$('#edit_calendar').fullCalendar('removeEvents', function (event) {
if (event.start.toDate() >= startDate && event.start.toDate() <= endDate
|| event.end.toDate() >= startDate && event.end.toDate() <= endDate) {
return true;
}
});
//Create events from rotation schedule selected
var newEvents = [];
var rotation_length = $('#rotation_type_select option:selected').val();
var rotation_start_date = new Date(startDate.toISOString());
var rotation_end_date = new Date(startDate.toISOString());
//End date is to midnight
endDate.setMinutes(endDate.getMinutes() + 1);
rotation_end_date.setDate(rotation_end_date.getDate() + parseInt(rotation_length));
var member_index = 0;
while (rotation_end_date <= endDate)
{
// alert('start date: ' + rotation_start_date.toISOString() + ' end date: ' + rotation_end_date.toISOString());
var event = new Object();
event = {
title: memberList[member_index].name,
start: new Date (rotation_start_date.toISOString()),
end: new Date (rotation_end_date.toISOString()),
objectID: memberList[member_index].id,
color: memberList[member_index].color,
allDay: true,
textColor: 'white'
};
newEvents.push(event);
eventsAdded.push(event);
rotation_start_date.setDate(rotation_start_date.getDate() + parseInt(rotation_length));
rotation_end_date.setDate(rotation_end_date.getDate() + parseInt(rotation_length));
if ((memberList.length - 1) == member_index) {
member_index = 0;
}
else {
member_index++;
}
}
//Render events on calendar
$('#edit_calendar').fullCalendar('addEventSource', newEvents);
}); //end create schedule button click
The function to convert the dates is the same as below but I renamed the function:
function convertTextToDate(dateValue)
{
var dateArray = dateValue.split(/\D/);
var pm = /pm$/i.test(dateValue);
var hour = (+dateArray[3] || 0) % 12 + (pm ? 12 : 0);
var date = new Date(Date.UTC(dateArray[2], dateArray[0] - 1, dateArray[1], hour, +dateArray[4] || 0, +dateArray[5] || 0));
return date;
}
What am i doing wrong?
Date.prototype.toISOString() is based on a 0 offset UTC timezone. So it is trying to normalize your current timezone back to 0 UTC, because when you do new Date() you create a new date based on your current time zone, that is why the method is trying to revert your date back to UTC time zone. You are probably right now in a time zone which is 4h behind UTC.
http://devdocs.io/javascript/global_objects/date/toisostring
In order to fix this, just append your string with " UTC" and it will no longer do the timezone shifting:
10/23/2015 12:00 AM UTC
It will generate:
"2015-10-23T00:00:00.000Z"
Do not use the Date constructor to parse strings, particularly non-standard strings. Ever. Manually parse the string.
Since you have a fixed format, it's pretty straight forward to create a date based on UTC with the format in the OP
// Parse date format mm/dd/yyyy hh:mm:ss AP as UTC
function parseMDYA(s) {
var b = s.split(/\D/);
var pm = /pm$/i.test(s);
var h = (+b[3]||0)%12 + (pm? 12 : 0);
return new Date(Date.UTC(b[2], b[0]-1, b[1], h, +b[4]||0, +b[5]||0));
}
var s = '10/23/2015 12:00 AM';
var d = parseMDYA(s);
document.write('Input string: ' + s +
'<br>UTC time: ' + d.toISOString() +
'<br>Local time: ' + d
);
Time parts that aren't supplied are treated as 0.

Categories