finally i write this method ( icluded datetime picker + convert date to Shamsi/Jalali and other helpers method for calculate vacation time
I use MdPersianDateTimePicker for datetime picker
https://github.com/Mds92/MD.BootstrapPersianDateTimePicker
All window.JSAPP.methods.* is my helpers function that i write for this method
// Get from server ( user config Or settings ) ( this check from server )
var work_group_start_time = window.work_group_start_time; // 09:00:00
var work_group_end_time = window.work_group_end_time; // 18:00:00
var work_group_thursday_start_time = window.work_group_thursday_start_time; // 09:00:00;
var work_group_thursday_end_time = window.work_group_thursday_end_time; // 15:00:00
var min_vacation_time_in_minute = window.min_vacation_time_in_minute; // 60
var max_vacation_time_in_hour = window.max_vacation_time_in_hour; // 18
var hollydays = window.hollydays; // ['2022-01-02']
var v_off_days = window.v_off_days; // ['Friday']
window.JSAPP.methods.disableFormOnSubmit('#vacation-create-form');
var submitButton = document.getElementById('submit_vacation');
var time_input = $("#vacation_time");
submitButton.classList.add("disabled");
submitButton.disabled = true;
var disabledDays = window.JSAPP.methods.disabledDays(v_off_days);
// my datetime picker and its configurations configs ( start date picker )
$('#start_date_text').MdPersianDateTimePicker({
trigger: 'click',
targetTextSelector: '#start_date_text',
targetDateSelector: '#start_date_date',
textFormat:'yyyy/MM/dd HH:mm',
dateFormat:'yyyy_MM_dd___HH__mm',
englishNumber: true,
inLine: false,
disableAfterToday: false,
//disableBeforeToday : true,
enableTimePicker: true,
fromDate: true,
disabledDays : disabledDays,
groupId: 'date_start_end-range',
disabledDates : window.JSAPP.methods.disabledDates(hollydays),
});
// my datetime picker and its configurations configs ( end datetime picker )
$('#end_date_text').MdPersianDateTimePicker({
trigger: 'click',
targetTextSelector: '#end_date_text',
targetDateSelector: '#end_date_date',
textFormat:'yyyy/MM/dd HH:mm',
dateFormat:'yyyy_MM_dd___HH__mm',
englishNumber: true,
inLine: false,
disableAfterToday: false,
enableTimePicker: true,
//disableBeforeToday : true,
toDate: true,
disabledDays : disabledDays,
groupId: 'date_start_end-range',
disabledDates : window.JSAPP.methods.disabledDates(hollydays),
});
// Calculate
var in_day_work_time = (((window.JSAPP.methods.parseTime(work_group_end_time) - window.JSAPP.methods.parseTime(work_group_start_time))/(1000*60))/60);
var in_day_work_thursday_time = (((window.JSAPP.methods.parseTime(work_group_thursday_end_time) - window.JSAPP.methods.parseTime(work_group_thursday_start_time))/(1000*60))/60);
vacationCalculate();
$("#start_date_date , #end_date_date").on('change keyup input focusout',function(){
vacationCalculate();
});
function vacationCalculate(){
time_input.removeClass('text-success');
time_input.removeClass('text-danger');
time_input.val('');
submitButton.classList.add("disabled");
submitButton.disabled = true;
function is_off_day(dayName,date){
if((v_off_days != "undefined" && window.in_array(dayName,v_off_days)) || (hollydays != "undefined" && window.in_array(date,hollydays))){
return true;
}
return false;
}
$("#vacation_time_help").html('');
var vacationTime = 0;
let start_at = $("#start_date_date").val();
let end_at = $("#end_date_date").val();
if((start_at && start_at != null && start_at != '' && start_at.length == 19) && (end_at && end_at != null && end_at != '' && end_at.length == 19)){
start_at = start_at.replace(/___/g,' ').replace(/__/g,':').replace(/_/g,'-');
start_at = start_at+':00';
end_at = end_at.replace(/___/g,' ').replace(/__/g,':').replace(/_/g,'-');
end_at = end_at+':00';
let start_date = start_at.split(' ')[0];
let end_date = end_at.split(' ')[0];
let start_time = start_at.split(' ')[1];
let end_time = end_at.split(' ')[1];
var max_off_time = 0;
// tStart = window.JSAPP.methods.parseTime(start_time,end_date.replace(/-/g,'/'));
// tStop = window.JSAPP.methods.parseTime(end_time,end_date.replace(/-/g,'/'));
var temp_dayName = window.JSAPP.methods.dayName(start_date,'string');
if(temp_dayName === 'Thursday'){
work_group_start_time = work_group_thursday_start_time;
work_group_end_time = work_group_thursday_end_time;
}
if(end_at && start_at){
if(end_at > start_at){
if(start_at !== end_at){
if(start_date === end_date){
let dayName = window.JSAPP.methods.dayName(start_date,'string');
if(!is_off_day(dayName,start_date)){
let _work_group_end_time = work_group_end_time;
if(dayName === 'Thursday'){
_work_group_end_time = work_group_thursday_end_time;
}
if(start_time <= work_group_start_time ){
start_time = work_group_start_time;
}
// if(end_time > _work_group_end_time || end_time < work_group_start_time ){
//
// end_time = _work_group_end_time;
//
// }
if(end_time > _work_group_end_time){
end_time = _work_group_end_time;
}
console.log(start_date+' '+start_time+' --- '+start_date+' '+end_time+' ---- '+((window.JSAPP.methods.parseTime(end_time,start_date) - window.JSAPP.methods.parseTime(start_time,start_date))/(1000*60)));
max_off_time = ((window.JSAPP.methods.parseTime(end_time,start_date) - window.JSAPP.methods.parseTime(start_time,start_date))/(1000*60));
}
}
else{
let start_at_timestamp = window.JSAPP.methods.stringToTimestamp(start_date+" "+"00:00:00");
let end_at_timestamp = window.JSAPP.methods.stringToTimestamp(end_date+" "+"23:59:59");
let vacation_diff = window.JSAPP.methods.diffInDay(start_at_timestamp,end_at_timestamp);
var days = parseInt(vacation_diff.day-1);
for(let i=0; i <= days; i++){
let thisDate;
let diffInM = 0;
let dayName;
thisDate = window.JSAPP.methods.addDays(window.JSAPP.methods.getSafeDate(start_date), i);
dayName = window.JSAPP.methods.dayName(thisDate,'date');
if(i === 0){
if(!is_off_day(dayName,start_date)){
let _work_group_end_time = work_group_end_time;
if(dayName === 'Thursday'){
_work_group_end_time = work_group_thursday_end_time;
}
let _work_group_start_time = work_group_start_time;
// 17:45 <= 18:00:00 && 15:45 >= 9:00:00
if(start_time <= _work_group_end_time && start_time >= work_group_start_time){
_work_group_start_time = start_time;
}
diffInM = ((window.JSAPP.methods.parseTime(_work_group_end_time,start_date) - window.JSAPP.methods.parseTime(_work_group_start_time,start_date))/(1000*60));
console.log(start_date+' '+_work_group_start_time+' --- '+start_date+' '+_work_group_end_time+' ---- '+((window.JSAPP.methods.parseTime(_work_group_end_time,start_date) - window.JSAPP.methods.parseTime(_work_group_start_time,start_date))/(1000*60)));
}
}
else {
if(!is_off_day(dayName,thisDate.yyyymmdd())){
let _work_group_end_time = work_group_end_time;
if(dayName === 'Thursday'){
_work_group_end_time = work_group_thursday_end_time;
}
if(i === days){
if(end_time <= _work_group_end_time && end_time >= work_group_start_time){
_work_group_end_time = end_time;
}
}
let _start_date = thisDate.yyyymmdd();
let _end_date = thisDate.yyyymmdd();
diffInM = ((window.JSAPP.methods.parseTime(_work_group_end_time,_end_date) - window.JSAPP.methods.parseTime(work_group_start_time,_start_date))/(1000*60));
console.log(_start_date+' '+work_group_start_time+' --- '+_end_date+' '+_work_group_end_time+' ---- '+((window.JSAPP.methods.parseTime(_work_group_end_time,_end_date) - window.JSAPP.methods.parseTime(work_group_start_time,_start_date))/(1000*60)));
}
}
if(diffInM > 0){
max_off_time += diffInM;
}
}
}
}
if(max_off_time !== 0){
vacationTime += max_off_time;
}
let calculate_vacation = window.JSAPP.methods.timeParser(vacationTime,9);
if(calculate_vacation.default_min >= min_vacation_time_in_minute){
if(calculate_vacation.day > 0){
$("#vacation_time_help").html('هر روز کاری برابر '+in_day_work_time+' ساعت');
}
if(calculate_vacation.default_min <= max_vacation_time_in_hour*60){
time_input.val(calculate_vacation.string);
time_input.removeClass('text-danger');
time_input.addClass('text-success');
submitButton.classList.remove("disabled");
submitButton.disabled = false;
}
else{
time_input.val('حداکثر مرخصی '+max_vacation_time_in_hour+' ساعت');
time_input.removeClass('text-success');
time_input.addClass('text-danger');
submitButton.classList.add("disabled");
submitButton.disabled = true;
}
}
else{
time_input.val('حداقل مرخصی '+min_vacation_time_in_minute+' دقیقه');
time_input.removeClass('text-success');
time_input.addClass('text-danger');
submitButton.classList.add("disabled");
submitButton.disabled = true;
}
}
else{
time_input.removeClass('text-success');
time_input.addClass('text-danger');
//زمان شروع باید کوچکتر از پایان باشد
time_input.val('بازه زمانی صحیحی انتخاب نشده است');
submitButton.classList.add("disabled");
submitButton.disabled = true;
}
}
else{
time_input.val('');
time_input.removeClass('text-success');
time_input.removeClass('text-danger');
if(end_at && start_at){
time_input.removeClass('text-success');
time_input.addClass('text-danger');
time_input.val('حداقل مرخصی '+min_vacation_time_in_minute+' دقیقه');
}
else{
time_input.removeClass('text-success');
time_input.removeClass('text-danger');
time_input.val('');
}
submitButton.classList.add("disabled");
submitButton.disabled = true;
}
}
}
used window.JSAPP.methods.*
'use strict';
var JSAPP = {
methods : {
addDays: function (theDate, days) {
if(typeof days === "undefined"){
days = 1;
}
if(days == 0){
return new Date(theDate.getTime());
}
else{
return new Date(theDate.getTime() + parseInt(days) * 24 * 60 * 60 * 1000);
}
},
dayName(dateString,format='string'){
let safeDate
if(format == 'string'){
safeDate = this.getSafeDate(dateString);
}
else{
safeDate = dateString;
}
let days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
let day = days[safeDate.getDay()];
if(safeDate && day){
return day;
}
},
subDays: function (theDate, days) {
if(typeof days === "undefined"){
days = 1;
}
return new Date(theDate.getTime() - parseInt(days) * 24 * 60 * 60 * 1000);
},
stringToTimestamp : function(datetime){
if(!isNaN(new Date(datetime).getDate())){
var arr_datetime;
if(datetime.search("-") !== -1 && datetime.search(":") !== -1){
arr_datetime = datetime.split(/[- :]/);
var sec = '00';
if(typeof arr_datetime[5] !== 'undefined'){
sec = arr_datetime[5];
}
return parseInt(new Date(arr_datetime[0], arr_datetime[1]-1, arr_datetime[2], arr_datetime[3], arr_datetime[4], sec).getTime().toString());
}
else{
if(datetime.search("-") !== -1){
arr_datetime = datetime.split(/-/);
return parseInt(new Date(arr_datetime[0], arr_datetime[1]-1, arr_datetime[2]).getTime().toString());
}
}
}
},
diffInDay(start,end){
var diffSec = Math.abs((end - start)/1000);
var diffMin = Math.ceil((diffSec) / 60);
var diffHrs = Math.ceil((diffSec) / 3600);
var diffDay_one = Math.ceil(diffHrs/(24));
var diffDay_two = Math.ceil(diffSec / (3600*24));
var diffDay = Math.ceil(diffSec / (3600*24));
return {
second: diffSec,
minute: diffMin,
hour : diffHrs,
day : diffDay,
diffDay_one : diffDay_one,
diffDay_two : diffDay_two,
}
},
timeParser: function(min,oneDayH=24){
var seconds = Number(min*60);
var d = Math.floor(seconds / (3600*oneDayH));
var h = Math.floor(seconds % (3600*oneDayH) / 3600);
var m = Math.floor(seconds % 3600 / 60);
var s = Math.floor(seconds % 60);
var result = '';
// var dDisplay = d > 0 ? d + (d == 1 ? " day, " : " days, ") : "";
// var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
// var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
// var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
var dDisplay = (d > 0 ? d : '');
var hDisplay = (h > 0 ? h : '');
var mDisplay = (m > 0 ? m : '');
var sDisplay = (s > 0 ? s : '');
if(dDisplay > 0){
result += dDisplay+' روز';
}
if(hDisplay > 0 && dDisplay > 0){
result += ' و '+hDisplay+' ساعت';
}
else if(hDisplay > 0 && dDisplay < 1){
result += hDisplay+' ساعت';
}
if(mDisplay > 0 && hDisplay > 0){
result += ' و '+mDisplay+' دقیقه';
}
else if(mDisplay > 0 && hDisplay < 1 && dDisplay < 1){
result += mDisplay+' دقیقه';
}
else if(mDisplay > 0 && hDisplay < 1 && dDisplay > 0 ){
result += ' و '+mDisplay+' دقیقه';
}
return {
string : result,
day : dDisplay,
hour : hDisplay,
minute : mDisplay,
second : sDisplay,
fullH : Math.ceil((min) / 60),
default_min : min
};
},
disabledDays : function(daysList){
let result = [];
if(daysList && daysList !== "undefined" && daysList.length > 0 && daysList != null && daysList != ''){
for(let i = 0 ; i < daysList.length; i++){
if(daysList[i] == 'Saturday' || daysList[i] == 0 ){
result.push(0);
}
else if( daysList[i] == 'Sunday' || daysList[i] == 1){
result.push(1);
}
else if( daysList[i] == 'Monday' || daysList[i] == 2){
result.push(2);
}
else if(daysList[i] == 'Tuesday' || daysList[i] == 3){
result.push(3);
}
else if(daysList[i] == 'Wednesday' || daysList[i] == 4){
result.push(4);
}
else if(daysList[i] == 'Thursday' || daysList[i] == 5){
result.push(5);
}
else if(daysList[i] == 'Friday' || daysList[i] == 6){
result.push(6);
}
}
}
return result;
},
disabledDates(ddates){
let dates = ddates;
let result = [];
if(dates && dates !== "undefined" && dates.length > 0 && dates != null && dates != ''){
if(!Array.isArray(ddates)){
if(this.canSplit(dates,',')) {
dates = dates.split(',');
}
else{
result.push(this.getSafeDate(dates));
}
}
for(let i=0;i<dates.length;i++){
result.push(this.getSafeDateSpliter(dates[i]));
}
}
return result;
},
canSplit : function(str, token){
return (str || '').split(token).length > 1;
},
getSafeDate: function(dateString){
if(dateString != null && dateString != ''){
let __start_at = null;
var start_at = dateString;
start_at = start_at.replace(/ /g,'');
var arr_start_at = null;
let _date = null;
let __date = null;
if(start_at.search("/") !== -1){
if(start_at.search(" ") !== -1){
_date = start_at.split(" ")[0].split("/");
__date = window.jalaali.toGregorian(parseInt(_date[0]), parseInt(_date[1]), parseInt(_date[2]));
}
else{
_date = start_at.split("/");
__date = window.jalaali.toGregorian(parseInt(_date[0]), parseInt(_date[1]), parseInt(_date[2]));
}
arr_start_at = parseInt(__date.gy) + '-' + ('0' + parseInt(__date.gm)).slice(-2) + '-' + ('0' + parseInt(__date.gd)).slice(-2);
}
else{
arr_start_at = start_at;
}
arr_start_at = arr_start_at.split('-');
__start_at = new Date(parseInt(arr_start_at[0]), parseInt(arr_start_at[1])-1, parseInt(arr_start_at[2]));
return __start_at;
}
else{
return false;
}
},
getSafeDateSpliter: function(dateString){
if(dateString != null && dateString != ''){
let __start_at = null;
let start_at = dateString.replace(/ /g,'');
var arr_start_at = null;
let _date = null;
let __date = null;
if(start_at.search("/") !== -1){
if(start_at.search(" ") !== -1){
_date = start_at.split(" ")[0].split("/");
__date = window.jalaali.toGregorian(parseInt(_date[0]), parseInt(_date[1]), parseInt(_date[2]));
}
else{
_date = start_at.split("/");
__date = window.jalaali.toGregorian(parseInt(_date[0]), parseInt(_date[1]), parseInt(_date[2]));
}
arr_start_at = parseInt(__date.gy) + '-' + ('0' + parseInt(__date.gm)).slice(-2) + '-' + ('0' + parseInt(__date.gd)).slice(-2);
}
else{
arr_start_at = start_at;
}
arr_start_at = arr_start_at.split('-');
__start_at = new Date(parseInt(arr_start_at[0]), parseInt(arr_start_at[1])-1, parseInt(arr_start_at[2]));
return __start_at;
}
else{
return false;
}
},
parseTime: function(cTime,date=null) {
if (cTime == '') return null;
var d = new Date();
if(date != null){
d = new Date(date);
}
var time = cTime.match(/(\d+)(:(\d\d))?\s*(p?)/);
d.setHours( parseInt(time[1]) + ( ( parseInt(time[1]) < 12 && time[4] ) ? 12 : 0) );
d.setMinutes( parseInt(time[3]) || 0 );
d.setSeconds(0, 0);
return d;
},
}
};
finaly i write backend code for calculate agian serverside and insert row per day and create vacation table and vacation details table