How do I restrict the JQuery Datepicker to show only bi-weekly Saturdays. I have successfully restricted it to show only weekly but could not figure out how to make it bi-weekly. See sample code below for weekly filter that allows for Saturdays only.
$("#datefilter").datepicker({
beforeShowDay: function(date){
if(date.getDay() === 6){
return [true];
}else{
return [false];
}
});
Did not test too much, but this should work for 1st and 3rd Saturday (5th too):
$(function() {
$("#datepicker").datepicker({
beforeShowDay: function(date){
var dayOfMonth = date.getDate()
if(date.getDay() === 6 && Math.floor((dayOfMonth - 1) / 7) % 2 === 0){
return [true];
}else{
return [false];
}
}
});
});
And if you want 2nd and 4th, replace 0 with 1 in 2nd part of if condition:
Math.floor((dayOfMonth - 1) / 7) % 2 === 1
UPDATE corrected calculation, should be (dayOfMonth - 1).
This is another option, if you anticipate needing to change to another day of the week you can seed it with a date that falls on that day:
function isAlternatingDay(testDate){
var seedDay = new Date(2018,11,3);
var daysDiff = (testDate - seedDay)/86400000;
return daysDiff % 14 === 0;
}
Related
I have call center and I use this JS code to let messages come in during business hours and after business hours/weekends it display a message saying that is outside of support time, my question is, how I make this code work also for holidays?
exports.handler = async function(context, event, callback) {
const moment = require('moment-timezone');
var now = moment().tz('America/New_York');
console.log('Current time-->'+now);
console.log('current hours-->'+now.hour());
let isWorkingHours = false;
//let isWorkingHours = true; // testing
const weekday = now.isoWeekday();
console.log('weekday-->'+weekday);
if (now.hour() >= 9 && now.hour() <= 17 && weekday <= 5) {
//if (now.hour() >= 4 && now.hour() <= 20 && weekday <= 2) { // testing
isWorkingHours = true;
//Console.log('This is outside working hours');
}
callback(null, {
isWorkingHours: isWorkingHours
});
}
I got this holiday checker from someone else's post here on StackOverflow (I should have documented the link, but I forgot to). You can iterate through all the dates you are interested in to create a complete list of holidays, or just check if a given date is a holiday
function check_holiday (dt_date) {
// check simple dates (month/date - no leading zeroes)
var n_date = dt_date.getDate(),
n_month = dt_date.getMonth() + 1;
var s_date1 = n_month + '/' + n_date;
if ( s_date1 == '1/1' // New Year's Day
|| s_date1 == '6/14' // Flag Day
|| s_date1 == '7/4' // Independence Day
|| s_date1 == '11/11' // Veterans Day
|| s_date1 == '12/25' // Christmas Day
) return true;
// weekday from beginning of the month (month/num/day)
var n_wday = dt_date.getDay(),
n_wnum = Math.floor((n_date - 1) / 7) + 1;
var s_date2 = n_month + '/' + n_wnum + '/' + n_wday;
if ( s_date2 == '1/3/1' // Birthday of Martin Luther King, third Monday in January
|| s_date2 == '2/3/1' // Washington's Birthday, third Monday in February
|| s_date2 == '5/3/6' // Armed Forces Day, third Saturday in May
|| s_date2 == '9/1/1' // Labor Day, first Monday in September
|| s_date2 == '10/2/1' // Columbus Day, second Monday in October
|| s_date2 == '11/4/4' // Thanksgiving Day, fourth Thursday in November
) return true;
// weekday number from end of the month (month/num/day)
var dt_temp = new Date (dt_date);
dt_temp.setDate(1);
dt_temp.setMonth(dt_temp.getMonth() + 1);
dt_temp.setDate(dt_temp.getDate() - 1);
n_wnum = Math.floor((dt_temp.getDate() - n_date - 1) / 7) + 1;
var s_date3 = n_month + '/' + n_wnum + '/' + n_wday;
if ( s_date3 == '5/1/1' // Memorial Day, last Monday in May
) return true;
// misc complex dates
if (s_date1 == '1/20' && (((dt_date.getFullYear() - 1937) % 4) == 0)
// Inauguration Day, January 20th every four years, starting in 1937.
) return true;
if (n_month == 11 && n_date >= 2 && n_date < 9 && n_wday == 2
// Election Day, Tuesday on or after November 2.
) return true;
return false;
}
The logic for checking if an specific instant in time is outside working ours is in your if statement.
I would abstract this in some sort of storage, based on time ranges for holidays or any day off. You could either have a table or cache where to store these holidays (you should load them in advance).
That way, you can do something like:
Search if there's a holiday whose date matches with the current date (matching just date without timestamp, you can use moment's isSame checking just by date)
If there's a match, return isWorkingHours as false
To check if the date matches, you can use this (regardless of current time, it returns true as you're comparing at date level):
console.log(moment('2021-05-10 14:00:00').isSame('2021-05-10', 'day'));
Here's a list of things that you might want to check for:
Weekends
"Static date" holidays (eg: Christmas)
"Variable date" holidays (eg: Easter)
Times (eg: your office opens at 8:00)
/* Function that checks if office is available at a specific date
* #returns {boolean}
*/
function is_office_available (date = new Date()) {
// weekends, or actually any other day of the week
let day = date.getDay();
if ( [0 /*sunday*/, 6 /*saturday*/].includes(day) ) return false;
// "static date" holidays (formatted as 'DD/MM')
let dd_mm = date.getDate() + '/' + (date.getMonth()+1);
if ( ['24/12', '25/12'].includes(dd_mm) ) return false;
// TODO: "variable date" holidays
// specific times
// this logic has to be extended a LOT if, for example, you have
// the office open from 8:30 to 17:30 with a launch break from 12:00 to 13:00 on weekdays
// and from 9:00 to 12:00 only on mondays
let hh = date.getHours();
if (9 < hh || hh > 17) return false;
// if no test returned true then the office is going to be available on that date
return true;
}
You can simply call this function in an if statement.
"Variable date" holidays have a quite a long (and boring) implementation to do and it depends on the ones you have in your country office.
I want to disable the 2nd Saturday, 4th Saturday, Sunday and public holidays, throughout the year, using jQuery Calendar.
Jquery Calendar plugin provide you a option "beforeShowDay", you can
find more information on DataPickerUI
To Disable 2nd Saturday & 4th Saturday, you need to first calculate the sat or sunday of specific month then disable those dates, like we did for others calendars
sample code calculate sat & sunday https://www.hscripts.com/scripts/JavaScript/second-fourth.php
Created plunker for you,
https://plnkr.co/edit/inBYY748BptaCd7Ulwwg?p=preview
//To disable Sundays you need to find out the Day of current date.
$(function () {
var publicHolidays = [
[11, 28, 2015],
[11, 30, 2015]
];
$("#datepicker").datepicker({
beforeShowDay: function (date) {
var day = date.getDay();
return [(day !== 0), ''];
}
});
//To disable public holidays create an array with you holiday list then
//return false when you browse calender.
$("#datepicker2").datepicker({
beforeShowDay: function (date) {
for (i = 0; i < publicHolidays.length; i++) {
if (date.getMonth() == publicHolidays[i][0] &&
date.getDate() == publicHolidays[i][1] &&
date.getFullYear() == publicHolidays[i][2]) {
return [false];
}
}
return [true];
}
});
});
For what it's worth, here's a couple of functions for the second/fourth Saturday part of the problem.
Both functions accept an instance of javascript Date() and return true or false. You can use either one.
function is2ndOr4thSat_1(date) {
var day = date.getDay(),
week = Math.floor(date.getDate() / 7);
return day == 6 && (week == 1 || week == 3)
}
Hopefully is2ndOr4thSat_1() is self explanatory.
function is2ndOr4thSat_2(date) {
var d = date.getDate(),
offset = (((1 + date.getDay() - d) % 7) + 7) % 7;
return !((offset + d) % 14);
}
is2ndOr4thSat_2() is more obscure.
The expression (((1 + date.getDay() - d) % 7) + 7) % 7 finds the offset of the first of the month from a nominal zero (the 1st's preceding Saturday), using a true modulo algorithm that caters for negative numbers.
Then (offset + d) % 14 returns 0 if date is either 14 or 28 days ahead of the nominal zero, and ! converts to a boolean of the required sense (true for qualifying Saturdays otherwise false).
In an order page I want to implement a calendar, in which, if the user is ordering on friday after 10am, then block the following saturday and sunday in delivery date calendar. Here is a sample code I am trying, but not working as intended.
beforeShowDay: function(date) {
var day = dt.getDay();
var hour = dt.getHours();
if (day == 4) {
// i think, here i want to put the code to disable days
}
}
If I use something like this
beforeShowDay: function(date) {
var day = date.getDay();
var dt = new Date();
var hour = dt.getHours();
return [(day != 5 && day != 6)];
}
I am able to disable Sat and Sun days, but this will disable all the Sat and Sun days. I wnat to disable only the very next Sat n Sun days to be disabled. Also I can get current Hour in var hour, So where should I use the condition to check if the hour is greater than 10am, I am using something like this but not working
beforeShowDay: function(date) {
var dt = new Date();
var hour = dt.getHours();
var day = date.getDay();
if (day == 4 && hour >= 10) {
return [(day != 5 && day != 6)];
}
}
Inside the beforeShowDay function, check the current date to see if it is a Friday and after 10am. If this is true then you also need to check if the date passed as argument is the next Saturday or Sunday:
$(function() {
$("#datepicker").datepicker({
beforeShowDay: function(date) {
// date (Friday March 13 2015 10:00 AM) is hardcoded for testing
var now = new Date(2015, 3 - 1, 13, 10, 0, 0, 0);
if (now.getDay() === 5 && now.getHours() >= 10) {
var now_plus_1 = new Date(now.getTime()); now_plus_1.setHours(0, 0, 0, 0); now_plus_1.setDate(now_plus_1.getDate() + 1);
var now_plus_2 = new Date(now.getTime()); now_plus_2.setHours(0, 0, 0, 0); now_plus_2.setDate(now_plus_2.getDate() + 2);
return [date.getTime() !== now_plus_1.getTime() && date.getTime() !== now_plus_2.getTime(), ""];
}
return [true, ""];
}
});
});
#import url("//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/ui-darkness/jquery-ui.min.css");
body { font-size: smaller; }
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<input id="datepicker">
$('#datepicker').datepicker({
beforeShowDay: function(date){
var dt = new Date(),
day = dt.getDay(),
hour = dt.getHours(),
twoDaysFrmNow = new Date().setDate(dt.getDate() + 2);
return [!(day == 5 && hour >= 10 && date <= twoDaysFrmNow && date > dt)];
}
});
beforeShowDayType: Function( Date date )
Default: null
A function that takes a date as a parameter and must return an array
with:
[0]: true/false indicating whether or not this date is selectable [1]:
a CSS class name to add to the date's cell or "" for the default
presentation [2]: an optional popup tooltip for this date
The function is called for each day in the datepicker before it is
displayed.
beforeShowDay: function(date) {
var day = dt.getDay();
var hour = dt.getHours();
if( day == 4) {
// this is an example of how to use
//first parameter is disable or not this date
//second parameter is the class you want to add ( jquery will remove the click listener, but you probebly want to style it like this date is not available
//third optional tootltip like 'closed on weekends'
return [false,'disabled','weekend']
}
}
Wondering if anyone has a solution for checking if a weekend exist between two dates and its range.
var date1 = 'Apr 10, 2014';
var date2 = 'Apr 14, 2014';
funck isWeekend(date1,date2){
//do function
return isWeekend;
}
Thank you in advance.
EDIT Adding what I've got so far. Check the two days.
function isWeekend(date1,date2){
//do function
if(date1.getDay() == 6 || date1.getDay() == 0){
return isWeekend;
console.log("weekend")
}
if(date2.getDay() == 6 || date2.getDay() == 0){
return isWeekend;
console.log("weekend")
}
}
Easiest would be to just iterate over the dates and return if any of the days are 6 (Saturday) or 0 (Sunday)
Demo: http://jsfiddle.net/abhitalks/xtD5V/1/
Code:
function isWeekend(date1, date2) {
var d1 = new Date(date1),
d2 = new Date(date2),
isWeekend = false;
while (d1 < d2) {
var day = d1.getDay();
isWeekend = (day === 6) || (day === 0);
if (isWeekend) { return true; } // return immediately if weekend found
d1.setDate(d1.getDate() + 1);
}
return false;
}
If you want to check if the whole weekend exists between the two dates, then change the code slightly:
Demo 2: http://jsfiddle.net/abhitalks/xtD5V/2/
Code:
function isFullWeekend(date1, date2) {
var d1 = new Date(date1),
d2 = new Date(date2);
while (d1 < d2) {
var day = d1.getDay();
if ((day === 6) || (day === 0)) {
var nextDate = d1; // if one weekend is found, check the next date
nextDate.setDate(d1.getDate() + 1); // set the next date
var nextDay = nextDate.getDay(); // get the next day
if ((nextDay === 6) || (nextDay === 0)) {
return true; // if next day is also a weekend, return true
}
}
d1.setDate(d1.getDate() + 1);
}
return false;
}
You are only checking if the first or second date is a weekend day.
Loop from the first to the second date, returning true only if one of the days in between falls on a weekend-day:
function isWeekend(date1,date2){
var date1 = new Date(date1), date2 = new Date(date2);
//Your second code snippet implies that you are passing date objects
//to the function, which differs from the first. If it's the second,
//just miss out creating new date objects.
while(date1 < date2){
var dayNo = date1.getDay();
date1.setDate(date1.getDate()+1)
if(!dayNo || dayNo == 6){
return true;
}
}
}
JSFiddle
Here's what I'd suggest to test if a weekend day falls within the range of two dates (which I think is what you were asking):
function containsWeekend(d1, d2)
{
// note: I'm assuming d2 is later than d1 and that both d1 and d2 are actually dates
// you might want to add code to check those conditions
var interval = (d2 - d1) / (1000 * 60 * 60 * 24); // convert to days
if (interval > 5) {
return true; // must contain a weekend day
}
var day1 = d1.getDay();
var day2 = d2.getDay();
return !(day1 > 0 && day2 < 6 && day2 > day1);
}
fiddle
If you need to check if a whole weekend exists within the range, then it's only slightly more complicated.
It doesn't really make sense to pass in two dates, especially when they are 4 days apart. Here is one that only uses one day which makes much more sense IMHO:
var date1 = 'Apr 10, 2014';
function isWeekend(date1){
var aDate1 = new Date(date1);
var dayOfWeek = aDate1.getDay();
return ((dayOfWeek == 0) || (dayOfWeek == 6));
}
I guess this is the one what #MattBurland sugested for doing it without a loop
function isWeekend(start,end){
start = new Date(start);
if (start.getDay() == 0 || start.getDay() == 6) return true;
end = new Date(end);
var day_diff = (end - start) / (1000 * 60 * 60 * 24);
var end_day = start.getDay() + day_diff;
if (end_day > 5) return true;
return false;
}
FIDDLE
Whithout loops, considering "sunday" first day of week (0):
Check the first date day of week, if is weekend day return true.
SUM "day of the week" of the first day of the range and the number of days in the lap.
If sum>5 return true
Use Date.getDay() to tell if it is a weekend.
if(tempDate.getDay()==6 || tempDate.getDay()==0)
Check this working sample:
http://jsfiddle.net/danyu/EKP6H/2/
This will list out all weekends in date span.
Modify it to adapt to requirements.
Good luck.
How can I get the code below to work when I have a month of february? Currently it is getting to the day and then stopping before getting to the if to determine whether it is a leap year.
if (month == 2) {
if (day == 29) {
if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) {
field.focus();
field.value = month +'/' + '';
}
}
else if (day > 28) {
field.focus();
field.value = month +'/' + '';
}
}
It's safer to use Date objects for datetime stuff, e.g.
isLeap = new Date(year, 1, 29).getMonth() == 1
Since people keep asking about how exactly this works, it has to do with how JS calculates the date value from year-month-day (details here). Basically, it first calculates the first of the month and then adds N -1 days to it. So when we're asking for the 29th Feb on a non-leap year, the result will be the 1st Feb + 28 days = 1st March:
> new Date(2015, 1, 29)
< Sun Mar 01 2015 00:00:00 GMT+0100 (CET)
On a leap year, the 1st + 28 = 29th Feb:
> new Date(2016, 1, 29)
< Mon Feb 29 2016 00:00:00 GMT+0100 (CET)
In the code above, I set the date to 29th Feb and look if a roll-over took place. If not (the month is still 1, i.e. February), this is a leap year, otherwise a non-leap one.
Compared to using new Date() this is is around 100 times faster!
Update:
This latest version uses a bit test of the bottom 3 bits (is it a multiple of 4), as well as a check for the year being a multiple of 16 (bottom 4 bits in binary is 15) and being a multiple of 25.
ily = function(y) {return !(y & 3 || !(y % 25) && y & 15);};
http://jsperf.com/ily/15
It is slightly faster again than my previous version (below):
ily = function(yr) {return !((yr % 4) || (!(yr % 100) && (yr % 400)));};
http://jsperf.com/ily/7
It is also 5% faster, compared to the already fast conditional operator version by broc.seib
Speed Test results: http://jsperf.com/ily/6
Expected logic test results:
alert(ily(1900)); // false
alert(ily(2000)); // true
alert(ily(2001)); // false
alert(ily(2002)); // false
alert(ily(2003)); // false
alert(ily(2004)); // true
alert(ily(2100)); // false
alert(ily(2400)); // true
isLeap = !(new Date(year, 1, 29).getMonth()-1)
...subtraction by one should work even faster than compare on most CPU architectures.
Correct and Fast:
ily = function(yr) { return (yr%400)?((yr%100)?((yr%4)?false:true):false):true; }
If you are in a loop or counting the nanoseconds, this is two magnitudes faster than running your year through a new Date() object. Compare the performance here: http://jsperf.com/ily
Better historical computation of leap years.
The code below takes into account that leap years were introduced in 45BC with the Julian calendar, and that the majority of the Western world adopted the Gregorian calendar in 1582CE, and that 0CE = 1BC.
isLeap = function(yr) {
if (yr > 1582) return !((yr % 4) || (!(yr % 100) && (yr % 400)));
if (yr >= 0) return !(yr % 4);
if (yr >= -45) return !((yr + 1) % 4);
return false;
};
Britain and its colonies adopted the Gregorian calendar in 1752, so if you are more Anglo centric this version is better (We'll assume Britain adopted the Julian calendar with Roman conquest starting in 43CE).
isLeap = function(yr) {
if (yr > 1752) return !((yr % 4) || (!(yr % 100) && (yr % 400)));
if (yr >= 43) return !(yr % 4);
return false;
};
JavaScript is expected to be getting a new Date/Time API which exposes a new global object - Temporal. This global object provides JS devs with a nicer way to deal with dates/times. It is currently a stage 3 proposal and should hopefully be available for use shortly.
The temporal api exposes a nice property for checking for leap years - inLeapYear. This returns true if a particular date is a leap year, otherwise false. Below we're using with() to convert the date returned by plainDateISO to one with our particular year:
const isLeap = year => Temporal.now.plainDateISO().with({year}).inLeapYear;
console.log(isLeap(2020)); // true
console.log(isLeap(2000)); // true
console.log(isLeap(1944)); // true
console.log(isLeap(2021)); // false
console.log(isLeap(1999)); // false
If you just want to check if your current system date time is a leap year, you can omit the .with():
// true if this year is a leap year, false if it's not a leap year
const isLeap = Temporal.now.plainDateISO().inLeapYear;
I use this because I hate having to keep referring to January as 0 and February as 1.
To me and PHP and readable dates, February=2. I know it doesn't really matter as the number never changes but it just keeps my brain thinking the same across different code.
var year = 2012;
var isLeap = new Date(year,2,1,-1).getDate()==29;
You can easily make this to work calling .isLeapYear() from momentjs:
var notLeapYear = moment('2018-02-29')
console.log(notLeapYear.isLeapYear()); // false
var leapYear = moment('2020-02-29')
console.log(leapYear.isLeapYear()); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.21.0/moment.min.js"></script>
all in one line 😉
const isLeapYear = (year) => (year % 100 === 0 ? year % 400 === 0 : year % 4 === 0);
console.log(isLeapYear(2016)); // true
console.log(isLeapYear(2000)); // true
console.log(isLeapYear(1700)); // false
console.log(isLeapYear(1800)); // false
console.log(isLeapYear(2020)); // true
function isLeap(year) {
if ( (year % 4 === 0 && year % 100 !== 0) || (year % 4 === 0 && year % 100 === 0 && year % 400 === 0) ) {
return 'Leap year.'
} else {
return 'Not leap year.';
}
}
Pseudo code
if year is not divisible by 4 then not leap year
else if year is not divisible by 100 then leap year
else if year is divisible by 400 then leap year
else not leap year
JavaScript
function isLeapYear (year) {
return year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 )
}
Using the above code insures you do only one check per year if the year is not divisible by 4
Just by adding the brackets you save 2 checks per year that is not divisible by 4
Another alternative is to see if that year has the date of February 29th. If it does have this date, then you know it is a leap year.
ES6
// Months are zero-based integers between 0 and 11, where Febuary = 1
const isLeapYear = year => new Date(year, 1, 29).getDate() === 29;
Tests
> isLeapYear(2016);
< true
> isLeapYear(2019);
< false
function leapYear(year){
if((year%4==0) && (year%100 !==0) || (year%400==0)){
return true;
}
else{
return false;
}
}
var result = leapYear(1700);
console.log(result);
Alternative non-conditionals solution:
const leapYear = y => (y % 4 === 0) + (y % 100 !== 0) + (y % 400 === 0) === 2
Use this:
Date.prototype.isLeap = function() {
return new Date(this.getFullYear(), 1, 29).getMonth() == 1;
};
Date.prototype.isLeap = function() {
return new Date(this.getFullYear(), 1, 29).getMonth() == 1;
};
console.log(new Date("10 Jan 2020").isLeap()); // True
console.log(new Date("10 Jan 2022").isLeap()); // False