I am using Node.JS and the excellent Moment library. I have a function that needs to generate an agenda of future dates (like an appointment system)
I have two timestamps representing the start and end of a period of time.
I want to create an array of date/times between these two times, dependent on a specific day and time of that day.
An example would be:
START DATE: 2019-01-26 15:00:01 (Saturday)
END DATE: 2019-02-23 15:00:00 (also a Saturday)
WE NEED: EVERY SATURDAY # 1500
EXPECTED ARRAY:
2019-02-02 15:00:00
2019-02-09 15:00:00
2019-02-16 15:00:00
2019-02-23 15:00:00
Please note: The start is not included in the array because it is later (by one second) than what we are looking for.
Any idea on how to accomplish this in Node?
const moment = require('moment')
const formatDate = date => moment(date).format('MMMM Do YYYY, h:mm:ss a')
const START_DATE = '2019-01-26 15:00:00'
const END_DATE = '2019-02-23 15:00:00'
let current = formatDate(START_DATE)
const end = formatDate(END_DATE)
let days = 7
let result = []
while (current > end) {
current = moment(START_DATE).add(days, 'days')
current = formatDate(current)
result.push(current)
days += 7
}
result.push(end)
result.forEach(date=>console.log(date))
import moment from 'moment';
const getDaysBetween = (startDate, endDate, day, time) => {
// Define a first day of result
let firstDay = moment(startDate)
.day(day)
.set('hour', time.match(/[\d]+(?=:)/g)[0])
.set('minutes', time.match(/(?<=:)[\d]+/g)[0])
.set('seconds', 0);
let resultDates = [ firstDay ];
// Add the rest
let weekBetweenThese = endDate.diff(firstDay, 'week');
Array(weekBetweenThese).fill({}).forEach((d, i) => {
resultDates.push(moment(firstDay).add(i + 1, 'weeks'))
});
// Filter out somecase that result day match with startDate & endDate but time condition goes wrong
resultDates = resultDates.filter(resultDate =>
startDate <= resultDate &&
resultDate <= endDate
);
return resultDates.map(resultDate => resultDate.toDate());
// return resultDates; // Return array of moment date.
};
console.log(
getDaysBetween(
moment('2019-01-26 15:00:01'),
moment('2019-02-23 15:00:00'),
'Saturday', '15:00'
)
)
https://codesandbox.io/s/wkpz72mo9w
Related
Here I am receiving the array of dates like this from the API,
let dates = ["22/1/2022","22/7/2022","9/10/2018"]
From these dates, I need to get the most recent date i.e 22/07/2022.
I got the below example from a site, This code works correctly only if the date matches the format of YYYY/MM/DD.
CODE
function max_date(all_dates) {
var max_dt = all_dates[0],
max_dtObj = new Date(all_dates[0]);
all_dates.forEach(function (dt, index) {
if (new Date(dt) > max_dtObj) {
max_dt = dt;
max_dtObj = new Date(dt);
}
});
return max_dt;
}
console.log(max_date(["2015/02/01", "2022/02/02", "2023/01/03"]));
Can we use some packages like date-fns or momentjs . to get the desired result despite the date format (or) with JS itself its achievable?
Please let me know your solution for this.
With date-fns you can do it like
import { max, parse } from "date-fns"
const dates = ["22/1/2022","22/7/2022","9/10/2018"];
console.log(max(dates.map((d) => parse(d, "d/M/yyyy", new Date()))))
// returns Fri Jul 22 2022 00:00:00 GMT+0200 (Central European Summer Time)
You can use pure Javascript for the logic
Convert strings to dates
Use timestamps (by getTime()) to find max
Convert that max timestamp back to date or string
const dates = ["22/1/2022", "22/7/2022", "9/10/2018"]
const convertStringToDate = (dateString) => {
const [day, month, year] = dateString.split("/");
return new Date(year, month - 1, day);
}
function format(inputDate) {
let date, month, year;
date = inputDate.getDate();
month = inputDate.getMonth() + 1;
year = inputDate.getFullYear();
return `${date}/${month}/${year}`;
}
const timestamps = dates.map(date => convertStringToDate(date).getTime())
const max = Math.max(...timestamps)
console.log(format(new Date(max)))
Sorting in descending order and returning the first element will do the work.
let dates = ['22/1/2022', '22/7/2022', '9/10/2018'];
const latestDate = (dates) => {
dates.sort((a, b) => {
const date1 = new Date(a.split('/').reverse().join('-'));
const date2 = new Date(b.split('/').reverse().join('-'));
return date2 - date1;
});
// First el will be latest date
return dates[0];
};
console.log(latestDate(dates));
// Output: 22/7/2022
I am trying to provide a default value for a TimePicker object. But the that value I have is a string e.g "12:00 PM" And the picker needs a Date object.
I tried parsing the time directly into a Date object like shown below, but it does not work
let startTime = new Date("12:00 PM");
How can i convert this time string into a Date object so that i can provide the default value to the TimePicker.
Ive been able to create a function that can do the conversion, since I did not find any solution to this.
const dateFromTime = ({ timeString }) => {
const dateTime = new Date();
let timeHours = parseInt(timeString.substring(0, 2));
let timeMinutes = parseInt(timeString.substring(3, 5));
let timeAMPM = timeString.substring(6,
if (timeAMPM === "PM") {
timeHours += 12;
dateTime.setHours( timeHours, timeMinutes, 0, 0);
return dateTime;
}
const dateTime = dateFromTime({ timeString: "12:00 PM" });
This get the current date and time and instead sets the time to the specified time. and returns that
For any improvements, please suggest the right way to do this.
HTML:
<input id="appt-time" type="time" name="appt-time" value="13:30">
JS
const timeFrom12hto24h = time12h => {
const [time, meridiem] = time12h.split(" ");
let [hours, minutes] = time.split(":");
if (hours === "12") hours = "00";
if (meridiem === "PM") hours = parseInt(hours, 10) + 12;
return {hours, minutes}
};
const getMyObjectTime= timeFrom12hto24h('12:00 PM');
// apply the time to the HTML element
document.getElementById("appt-time").value = getMyObjectTime.hours + ':' + getMyObjectTime.minutes;
// one way to generate the needed time object
const dateInMiliseconds = new Date().setHours(getMyObjectTime.hours, getMyObjectTime.minutes, 0)
console.log(dateInMiliseconds);
In case there is moment.js already used in the project it would be like this:
HTML:
<input id="appt-time" type="time" name="appt-time" value="13:30">
JS:
// apply the time to the HTML element
document.getElementById("appt-time").value = moment("01:00 PM", 'hh:mm A').format('HH:mm')
// one way to generate the needed time object
let [hour, minutes] = moment("01:00 PM", 'hh:mm A').format('HH,mm').split(',');
const dateInMiliseconds = new Date().setHours(hour,minutes, 0)
console.log(dateInMiliseconds);
You just need to give the correct format to the Date object.
solution 1
If you don't care about date then you can simply convert like this.
let startTime = new Date(`2022/01/01 12:00 PM`);
solution 2
If you need today's date then you can simply convert like this.
let startTime = new Date(`${new Date().toDateString()} 12:00 PM`)
I used date-and-time package to format current time. It's worked for me.
npm install date-and-time
Controller
const date = require("date-and-time");
const now = new Date();
const startTime = date.format(now, "HH:mm:ss");
I have 2 dates with hours:
Start: 2019-09-06 14:00:00
End: 2019-09-9 19:30:00
I need to list all subrange days (full or partial) inside the range, also with hours, in this example:
2019-09-06 14:00:00 to 2019-09-06 23:59:59
2019-09-07 00:00:00 to 2019-09-07 23:59:59
2019-09-08 00:00:00 to 2019-09-08 23:59:59
2019-09-09 00:00:00 to 2019-09-09 19:30:00
in an array like:
result = array(
0 => array(
"Start" => 2019-09-06 14:00:00,
"End" => 2019-09-06 23:59:59
),
1 => array(
"Start" => 2019-09-07 00:00:00,
"End" => 2019-09-07 23:59:59
),
...
)
I have found similar script to list all days like:
var enumerateDaysBetweenDates = function(startDate, endDate) {
var dates = [];
var currDate = moment(startDate).startOf('day');
var lastDate = moment(endDate).startOf('day');
while(currDate.add(1, 'days').diff(lastDate) < 0) {
console.log(currDate.toDate());
dates.push(currDate.clone().toDate());
}
return dates;
};
But it doesn't consider hour and subrange like I need.
I'd like to use moment.js to simplify all the job but i'm not sure how to start with.
Any suggest how to "recognize" different days?
That was a fun exercise with moment.js. The idea is to collect list of day starts and ends separately:
var start = "2019-09-06 14:00:00";
var end = "2019-09-9 19:30:00";
var startMoment = moment(start);
var endMoment = moment(end);
var starts = [startMoment.toDate()];
var ends = [];
var dayBeforeEnd = moment(endMoment).subtract(1, 'days');
for (var m = moment(startMoment); m.isBefore(dayBeforeEnd); m.add(1, 'days')) {
ends.push(moment(m).endOf('day').toDate());
starts.push(moment(m).add(1, 'days').startOf('day').toDate());
}
ends.push(endMoment.toDate());
Now starts[i] and ends[i] contains corresponding day start and end as Date objects.
One may notice a lot of moment(moment_object) happening. That is because moment objects are mutable, so you need to clone it every time you need to add or subtract some timerange.
You don't need to load moment for that.
In JavaScript, the Date object has setHour(), setMinutes() and so on. You can get the current date, sum 24 hours and get the date again.
For example:
function getRanges(start, end) {
start = new Date(start).getTime(); // Sanitize input
end = new Date(end).getTime();
var list = [];
var current = start;
while(current < end) {
var date = new Date(current); // Get current date
// Set the date to just before midnight.
date.setHours(23);
date.setMinutes(59);
date.setSeconds(59);
date.setMilliseconds(999);
// Now you have the next element in the range
var next = date.getTime();
if (next > end) { // Don't surpass the end
next = end;
}
// create a range using the current and the end of the day before midnight
list.push({
start: current,
end: next
});
current = next+1; // Go to the very next day
}
return list;
}
var ranges = getRanges(Date.now()-(7*24*60*60*1000), Date.now());
// You can convert them to dates if you want
for (var i = 0; i < ranges.length; i++) {
ranges[i].start = new Date(ranges[i].start).toLocaleString();
ranges[i].end = new Date(ranges[i].end).toLocaleString();
}
console.log(ranges);
I need to list week array from 2017 till now. My week start from Monday and ends with Sunday I tried to do in moment.js,
const startDate = moment().isoWeekday('Monday').format('DD-MM-YYYY');
const endDate = moment().isoWeekday('Sunday').format('DD-MM-YYYY');
I tried to like this to get the week start date and end date but I don't know the process to next step.
Note my array list start with ["02-01-2017", "08-01-2017"] and ends with current week will be the Last one.
const result = [["02-01-2017", "08-01-2017"],...... ["05-01-2018", "11-01-2018"]]
You can initialize your start date to 1st weekday of 1st January 2017 and iterate to all the dates less than today and keep adding days in an array.
var weeks = [];
var startDate = moment(new Date(2017,0,1)).isoWeekday(8);
if(startDate.date() == 8) {
startDate = startDate.isoWeekday(-6)
}
var today = moment().isoWeekday('Sunday');
while(startDate.isBefore(today)) {
let startDateWeek = startDate.isoWeekday('Monday').format('DD-MM-YYYY');
let endDateWeek = startDate.isoWeekday('Sunday').format('DD-MM-YYYY');
startDate.add(7,'days');
weeks.push([startDateWeek,endDateWeek]);
}
console.log(weeks)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
Something like that would help?
let startDate = moment('2017-01-01').startOf('week').format('YYYY-MM-DD');
let endDate = moment(new Date()).startOf('week').format('YYYY-MM-DD');
const weeks = [];
while (startDate <= endDate) {
weeks.push(startDate);
startDate = moment(startDate).add(7, 'days').format('YYYY-MM-DD');
}
console.log('weeks:', weeks);
I have this date "2016-04-23T11:45:00Z" and I want to check this date in this week or not ?
Thanks,
Dates are hard, I would always suggest using a library dedicated to date handling as it reduces the chances of errors in your code.
MomentJS is a good one.
var now = moment();
var input = moment("2016-04-17T11:45:00Z");
var isThisWeek = (now.isoWeek() == input.isoWeek())
Edit: Please note as of 2020 moment may not be a good choice for new projects
This seems to be working for me.
function isDateInThisWeek(date) {
const todayObj = new Date();
const todayDate = todayObj.getDate();
const todayDay = todayObj.getDay();
// get first date of week
const firstDayOfWeek = new Date(todayObj.setDate(todayDate - todayDay));
// get last date of week
const lastDayOfWeek = new Date(firstDayOfWeek);
lastDayOfWeek.setDate(lastDayOfWeek.getDate() + 6);
// if date is equal or within the first and last dates of the week
return date >= firstDayOfWeek && date <= lastDayOfWeek;
}
const date = new Date();
const isInWeek = isDateInThisWeek(date);
<div ng-app="myApp">
<div class="container" ng-controller="Ctrl_List">
<h1>{{currentDate}}</h1>
<h1>{{numberCurrentDateWeeks}}</h1>
<h1>{{yourDate}}</h1>
<h1>{{numberYourDateWeeks}}</h1>
</div>
</div>
......
angular.module('myApp', [])
.controller("Ctrl_List", ["$scope", "$filter", function(s, $filter) {
s.yourDate = '2016-04-23T11:45:00Z'
s.currentDate = new Date();
s.numberCurrentDateWeeks = $filter('date')(s.currentDate, "w");
s.numberYourDateWeeks = $filter('date')(s.yourDate, "w");
}]);
then you got the Week numbers just compare or do whatever you like
cheers !
You can do that without any libraries by checking if the date.getTime() (milliseconds since epoch) is between last monday and next monday:
const WEEK_LENGTH = 604800000;
function onCurrentWeek(date) {
var lastMonday = new Date(); // Creating new date object for today
lastMonday.setDate(lastMonday.getDate() - (lastMonday.getDay()-1)); // Setting date to last monday
lastMonday.setHours(0,0,0,0); // Setting Hour to 00:00:00:00
const res = lastMonday.getTime() <= date.getTime() &&
date.getTime() < ( lastMonday.getTime() + WEEK_LENGTH);
return res; // true / false
}
(one week in ms = 24 * 60 * 60 * 1000 * 7 = 604,800,000)
May not be the most optimal solution, but I think it's quite readable:
function isThisWeek (date) {
const now = new Date();
const weekDay = (now.getDay() + 6) % 7; // Make sure Sunday is 6, not 0
const monthDay = now.getDate();
const mondayThisWeek = monthDay - weekDay;
const startOfThisWeek = new Date(+now);
startOfThisWeek.setDate(mondayThisWeek);
startOfThisWeek.setHours(0, 0, 0, 0);
const startOfNextWeek = new Date(+startOfThisWeek);
startOfNextWeek.setDate(mondayThisWeek + 7);
return date >= startOfThisWeek && date < startOfNextWeek;
}
This link explaines, how to do this without using any js libraries. https://gist.github.com/dblock/1081513
Code against link death:
function( d ) {
// Create a copy of this date object
var target = new Date(d.valueOf());
// ISO week date weeks start on monday
// so correct the day number
var dayNr = (d.getDay() + 6) % 7;
// Set the target to the thursday of this week so the
// target date is in the right year
target.setDate(target.getDate() - dayNr + 3);
// ISO 8601 states that week 1 is the week
// with january 4th in it
var jan4 = new Date(target.getFullYear(), 0, 4);
// Number of days between target date and january 4th
var dayDiff = (target - jan4) / 86400000;
// Calculate week number: Week 1 (january 4th) plus the
// number of weeks between target date and january 4th
var weekNr = 1 + Math.ceil(dayDiff / 7);
return weekNr;
}
I managed to do it with this simple trick and without any external library.
Considering monday as the first day of the week, the function takes as parameter a date string and do the validation before checking if the day indeed is in the current week.
function isInThisWeek(livr){
const WEEK = new Date()
// convert delivery date to Date instance
const DATEREF = new Date(livr)
// Check if date instance is in valid format (depends on the function arg)
if(DATEREF instanceof Date && isNaN(DATEREF)){
console.log("invalid date format")
return false}
// Deconstruct to get separated date infos
const [dayR, monthR, yearR] = [DATEREF.getDate(), DATEREF.getMonth(), DATEREF.getFullYear()]
// get Monday date
const monday = (WEEK.getDate() - WEEK.getDay()) + 1
// get Saturday date
const sunday = monday + 6
// Start verification
if (yearR !== WEEK.getFullYear()) { console.log("WRONG YEAR"); return false }
if (monthR !== WEEK.getMonth()) { console.log("WRONG MONTH"); return false }
if(dayR >= monday && dayR <= sunday) { return true }
else {console.log("WRONG DAY"); return false}
}
In the comments I saw that you stated that your week starts on Monday.
In that case, I guess it'd be a good idea to calculate the ISO week number of the 2 dates and see if you get the same week number for both of them.
To calculate the ISO week number, check this answer:
In case anyone else's week starts on Sunday instead, you can use this answer to calculate the week number accordingly.
then you can do something like this:
function isSameWeek(date1, date2) {
return date1.getWeekNumber() === date2.getWeekNumber();
}
const isDateInThisWeek = (date) => {
const today = new Date();
//Get the first day of the current week (Sunday)
const firstDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay())
);
//Get the last day of the current week (Saturday)
const lastDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay() + 6)
);
//check if my value is between a minimum date and a maximum date
if (date >= firstDayOfWeek && date <= lastDayOfWeek) {
return true;
} else {
return false;
}
};