JavaScript forEach. String elements to date - javascript

I have an array of strings scheduleDates:
0:"24.04.2016, 11:53"
1:"12.04.2016, 10:07"
2:"13.04.2016, 9:45"
I need to replace the string elements to Date type in the same array.
I tried:
scheduleDates.forEach(function (date) {
var currDate = date.split(', ')[0];
var currTime = date.split(', ')[1];
var hours = currTime.split(':')[0];
var minutes = currTime.split(':')[1];
var year = currDate.split('.')[2];
var month = currDate.split('.')[1];
var day = currDate.split('.')[0];
var newDate = new Date(year, month, day, hours, minutes);
date = newDate;
});
It doesn't work

First of all you should use map instead of forEach. It better fits your purpose.
Here is what I would do (by following your initial thoughts):
function toDateObject(date) {
var currDate = date.split(', ')[0];
var currTime = date.split(', ')[1];
var hours = currTime.split(':')[0];
var minutes = currTime.split(':')[1];
var year = currDate.split('.')[2];
var month = currDate.split('.')[1];
var day = currDate.split('.')[0];
return new Date(year, month, day, hours, minutes);
}
var scheduleDates = ["24.04.2016, 11:53","12.04.2016, 10:07","13.04.2016, 9:45"].map(toDateObject);
Array.prototype.map applies the function given as argument to each element of the array and the collects all the result in a new array which is the result.
In this case it receives an array of strings, applies the toDateObject function to each of them and then returns a new array of the results of that function calls.
Read more about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

date is a variable that is local to every function call. You're assigning to this local variable, not the position in the array.
An ugly fix is to assign the new value to the correct index. This is a bit hacky, and generally not what forEach is intended for.
scheduleDates.forEach(function (date, index) {
var currDate = date.split(', ')[0];
var currTime = date.split(', ')[1];
var hours = currTime.split(':')[0];
var minutes = currTime.split(':')[1];
var year = currDate.split('.')[2];
var month = currDate.split('.')[1];
var day = currDate.split('.')[0];
var newDate = new Date(year, month, day, hours, minutes);
scheduleDates[index] = newDate;
});
You could instead use map, and assign the resulting array back into your variable.
scheduleDates = scheduleDates.map(function (date) {
// ...
return newDate;
});
Or roll your own destructive map, to make things a little easier.
function mapd (array, block) {
var length = array.length;
for (var i = 0; i < length; i++) {
array[i] = block(array[i], i);
}
}
mapd(scheduleDates, function (date) {
// ...
return newDate;
});

var scheduleDates = ["24.04.2016, 11:53","12.04.2016, 10:07","13.04.2016, 9:45"];
scheduleDates = scheduleDates.map(function (date) {
var currDate = date.split(', ')[0];
var currTime = date.split(', ')[1];
var hours = currTime.split(':')[0];
var minutes = currTime.split(':')[1];
var year = currDate.split('.')[2];
var month = currDate.split('.')[1];
var day = currDate.split('.')[0];
return new Date(year, month-1, day, hours, minutes);
});

Related

Convert date string into proper date in Javascript

I get an array with dates as string from the server, now I want to filter only day, month and year. How can I format the filter result to a certain date format?
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00', ...];
//wanted result: 2015-02-04 or 04.02.2015
You could convert your what's look to be an ISO Date format like this:
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00'];
date.map(function(_d) {
var d = new Date(_d)
return d.getFullYear() + '-' + d.getMonth() + 1 + '-' + d.getDay()
}
// if you want to get fancy, you could throw in this function to pad the days and months:
var pad = function (n) {return n<10? '0'+n:''+n;}
var sorted = date.map(function(_d) {
var d = new Date(_d)
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDay())
})
console.log(sorted);
Date can take an argument of a string. Use a for loop to iterate through your list, and then make a new Date object for each one.
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00']
var dateObjects = [];
for (var i = 0; i<date.length; i++) {
d = new Date(date[i]);
dateObjects.push(d);
}
Or, in a single line:
var dateObjects = date.map( function (datestr) {return new Date(datestr)} );
Now, you can find the month, day, and year from one of these by the following methods:
var year = dateObjects[0].getFullYear(); // Gets the year
var month = dateObjects[0].getMonth()+1; // Gets the month (add 1 because it's zero-based)
var day = dateObjects[0].getDate(); // Gets the day of the month
dateObjects[0] is just an example that refers to the first date in the list.
So you can then get your output string like
var dateStrings = dateObjects.map(function (item) {
return item.getFullYear()+"-"+(item.getMonth()+1)+"-"+item.getDate();
})
var date = ['2015-02-04T23:54:00.000+01:00','2015-02-04T23:54:00.000+01:00'];
var newdateobject = [];
$.each( date, function(key, e) {
var a = new Date(e);
newdateobject.push(a.getFullYear()+'-'+(a.getMonth()+1) +'-'+a.getDate());
});
IF the format you mentioned is consistent, then:
date.forEach(function(d) {
d = d.substring(0, 10);
})

How to get the holidays date in my case?

I am trying to get the holidays of given range of dates.
For example:
var holiday = ['2014-01-01','2014-07-04','2014-12-24', '2014-12-25'...other holidays elements ];
var startDate = '2014-08-01'
var endDate = '2014-12-30';
var holidays=getHolidays(startDate, endDate);
//console.log(holidays) -> output 2014-12-24 and 2014-12-25.
getHolidays = function(startDate, endDate) {
var holidays=[];
//not sure how to get holidays here....
return holidays
}
I was hoping to write a function to get 2014-12-24 and 2014-12-25. My brain is fried now and I don't know what's the best approach on this. Can anyone help me about it? Thanks a lot!
The solution is to use filter function of array. The first parameter is the array you need to filter, and in your case, it's ['2014-01-01', '2014-07-04', '2014-12-24', '2014-12-25'].
var getHolidays = function(holiday,startDate, endDate) {
return holiday.filter(function(element){
var start = new Date(startDate);
var end = new Date(endDate);
var temp = new Date(element);
return temp >= start && temp <= end;
});
}
var holiday = ['2014-01-01', '2014-07-04', '2014-12-24', '2014-12-25'];
var startDate = '2014-08-01'
var endDate = '2014-12-30';
var holidays = getHolidays(holiday,startDate, endDate); //["2014-12-24", "2014-12-25"]
It works exactly as what you expect as shown in
JSFiddle
You could try turning them into date objects, and then comparing them that way. Something like:
var holidays = ['2014-01-01','2014-07-04','2014-12-24', '2014-12-25'];
var startDate = '2014-08-01';
var endDate = '2014-12-30';
var getHolidays = function(startDate, endDate) {
var startTime = new Date(startDate).getTime();
var endTime = new Date(endDate).getTime();
var output = [];
holidays.forEach(function(holiday) {
var holidayTime = new Date(holiday).getTime();
if (holidayTime >= startTime && holidayTime <= endTime) {
output.push(holiday);
}
});
return output;
}
var holidays = getHolidays(startDate, endDate);
console.log(holidays);
As plain strings, the getHolidays function can be:
// Get holidays between two dates
function getHolidays(startDate, endDate) {
var output = [];
var i = 0;
var holiday;
while ((holiday = holidays[i++]) && holiday < endDate) {
if (startDate <= holiday) {
output.push(holiday)
}
}
return output;
}
If you are using ISO 8601 date strings, there's no need to convert them to Date objects. One of the reasons for the ISO format is that in most systems, you can compare strings directly rather than Date objects or some number value.
You can also parse the strings to Date objects, then use those to do the calculations but it takes more code for no real benefit:
// Parse date string in y-m-d format
function parseYMD(s) {
var b = s.split(/\D/);
var d = new Date();
d.setHours(0,0,0,0);
d.setFullYear(b[0], --b[1], b[2]);
return d.getFullYear() == b[0] && d.getDate() == b[2]? d : NaN;
}
// Holiday array
var holidays = ['2014-01-01','2014-07-04','2014-12-24', '2014-12-25'];
// Get holidays between two dates
function getHolidays(startDate, endDate) {
startDate = parseYMD(startDate);
endDate = parseYMD(endDate);
var output = [];
var i = 0;
var holiday;
for (var i=0, iLen=holidays.length; i<iLen; i++) {
holiday = parseYMD(holidays[i]);
if (holiday <= endDate) {
if (holiday >= startDate) {
output.push(holidays[i]);
}
}
}
return output;
}
console.log(getHolidays('2014-08-01', '2014-12-30')); // ["2014-12-24", "2014-12-25"]

Javascript OO Function

I need something obvious pointing out to me in regard to JS functions.
The following code works, but I want to call upon it anywhere:
var pattern = /(\d{2})\-(\d{2})\-(\d{4})/;
var date = entry.date.split(' ');
var date = date[0];
var date = new Date(date.replace(pattern,'$3-$2-$1'));
var year = date.getYear();
var month = date.getMonth();
var day = date.getDay();
What would be the best practice to place this in a global function so I can just do adjustDate(string). Double points (Sadly, not in my power) to explain how I would then also have access to all the objects such as year, month, day.
Thanks in advance!
Can't you just declare the function?
function adjustDate(entry) {
var date = entry.date.split(' ');
date = date[0];
date = new Date(date.replace(/(\d{2})\-(\d{2})\-(\d{4})/, '$3-$2-$1'));
return {
year: date.getYear(),
month: date.getMonth(),
day: date.getDay()
};
}
I would just return a date without abstracting its existing methods
function AdjustedDate(dateString)
{
return new Date(dateString.split(' ')[0].replace(/(\d{2})\-(\d{2})\-(\d{4})/, '$3-$2-$1'));
}
var ad = AdjustedDate(entry.date);
alert(ad);
alert(ad.getDay());
Pass the entry into the function and then pass an object containing the information you want out. Then just access it like you would an ordinary JS object.
function adjustDate(entry) {
var pattern = /(\d{2})\-(\d{2})\-(\d{4})/;
var date = entry.date.split(' ');
var date = date[0];
var date = new Date(date.replace(pattern,'$3-$2-$1'));
var year = date.getYear();
var month = date.getMonth();
var day = date.getDay();
return { day: day, month: month, year: year }
}
var dateObject = adjustDate(/*entry*/)
dateObject.day // day
dateObject.month // month

Dates between two dates

I have for example two dates:
var first = '2013-07-30';
var second = '2013-08-04';
How can i show all dates between first and second?
This should return me:
2013-07-30
2013-07-31
2013-08-01
2013-08-02
2013-08-03
2013-08-04
In PHP I can get dates to strtotime and use a while loop. But how can I do it in jQuery?
I would like have this in array.
var day = 1000*60*60*24;
date1 = new Date('2013-07-30');
date2 = new Date("2013-08-04");
var diff = (date2.getTime()- date1.getTime())/day;
for(var i=0;i<=diff; i++)
{
var xx = date1.getTime()+day*i;
var yy = new Date(xx);
console.log(yy.getFullYear()+"-"+(yy.getMonth()+1)+"-"+yy.getDate());
}

Loop through a date range with JavaScript

Given two Date() objects, where one is less than the other, how do I loop every day between the dates?
for(loopDate = startDate; loopDate < endDate; loopDate += 1)
{
}
Would this sort of loop work? But how can I add one day to the loop counter?
Thanks!
Here's a way to do it by making use of the way adding one day causes the date to roll over to the next month if necessary, and without messing around with milliseconds. Daylight savings aren't an issue either.
var now = new Date();
var daysOfYear = [];
for (var d = new Date(2012, 0, 1); d <= now; d.setDate(d.getDate() + 1)) {
daysOfYear.push(new Date(d));
}
Note that if you want to store the date, you'll need to make a new one (as above with new Date(d)), or else you'll end up with every stored date being the final value of d in the loop.
Based on Tom GullenĀ“s answer.
var start = new Date("02/05/2013");
var end = new Date("02/10/2013");
var loop = new Date(start);
while(loop <= end){
alert(loop);
var newDate = loop.setDate(loop.getDate() + 1);
loop = new Date(newDate);
}
I think I found an even simpler answer, if you allow yourself to use Moment.js:
// cycle through last five days, today included
// you could also cycle through any dates you want, mostly for
// making this snippet not time aware
const currentMoment = moment().subtract(4, 'days');
const endMoment = moment().add(1, 'days');
while (currentMoment.isBefore(endMoment, 'day')) {
console.log(`Loop at ${currentMoment.format('YYYY-MM-DD')}`);
currentMoment.add(1, 'days');
}
<script src="https://cdn.jsdelivr.net/npm/moment#2/moment.min.js"></script>
If startDate and endDate are indeed date objects you could convert them to number of milliseconds since midnight Jan 1, 1970, like this:
var startTime = startDate.getTime(), endTime = endDate.getTime();
Then you could loop from one to another incrementing loopTime by 86400000 (1000*60*60*24) - number of milliseconds in one day:
for(loopTime = startTime; loopTime < endTime; loopTime += 86400000)
{
var loopDay=new Date(loopTime)
//use loopDay as you wish
}
Here simple working code, worked for me
var from = new Date(2012,0,1);
var to = new Date(2012,1,20);
// loop for every day
for (var day = from; day <= to; day.setDate(day.getDate() + 1)) {
// your day is here
console.log(day)
}
var start = new Date("2014-05-01"); //yyyy-mm-dd
var end = new Date("2014-05-05"); //yyyy-mm-dd
while(start <= end){
var mm = ((start.getMonth()+1)>=10)?(start.getMonth()+1):'0'+(start.getMonth()+1);
var dd = ((start.getDate())>=10)? (start.getDate()) : '0' + (start.getDate());
var yyyy = start.getFullYear();
var date = dd+"/"+mm+"/"+yyyy; //yyyy-mm-dd
alert(date);
start = new Date(start.setDate(start.getDate() + 1)); //date increase by 1
}
As a function,
function getDatesFromDateRange(from, to) {
const dates = [];
for (let date = from; date <= to; date.setDate(date.getDate() + 1)) {
const cloned = new Date(date.valueOf());
dates.push(cloned);
}
return dates;
}
const start = new Date(2019, 11, 31);
const end = new Date(2020, 1, 1);
const datesArray = getDatesFromDateRange(start, end);
console.dir(datesArray);
Based on Tabare's Answer,
I had to add one more day at the end, since the cycle is cut before
var start = new Date("02/05/2013");
var end = new Date("02/10/2013");
var newend = end.setDate(end.getDate()+1);
var end = new Date(newend);
while(start < end){
alert(start);
var newDate = start.setDate(start.getDate() + 1);
start = new Date(newDate);
}
Didn't want to store the result in an array, so maybe using yield?
/**
* #param {object} params
* #param {Date} params.from
* #param {Date} params.to
* #param {number | undefined} params.incrementBy
* #yields {Date}
*/
function* iterateDate(params) {
const increaseBy = Math.abs(params.incrementBy ?? 1);
for(let current = params.from; current.getTime() <= params.to.getTime(); current.setDate(current.getDate() + increaseBy)) {
yield new Date(current);
}
}
for (const d of iterateDate({from: new Date(2021,0,1), to: new Date(2021,0,31), incrementBy: 1})) {
console.log(d.toISOString());
}
If you want an efficient way with milliseconds:
var daysOfYear = [];
for (var d = begin; d <= end; d = d + 86400000) {
daysOfYear.push(new Date(d));
}
Let us assume you got the start date and end date from the UI and stored it in the scope variable in the controller.
Then declare an array which will get reset on every function call so that on the next call for the function the new data can be stored.
var dayLabel = [];
Remember to use new Date(your starting variable) because if you dont use the new date and directly assign it to variable the setDate function will change the origional variable value in each iteration`
for (var d = new Date($scope.startDate); d <= $scope.endDate; d.setDate(d.getDate() + 1)) {
dayLabel.push(new Date(d));
}
Based on Jayarjo's answer:
var loopDate = new Date();
loopDate.setTime(datFrom.valueOf());
while (loopDate.valueOf() < datTo.valueOf() + 86400000) {
alert(loopDay);
loopDate.setTime(loopDate.valueOf() + 86400000);
}

Categories