/* $Revision$ $Id$ File: date.js Description: Datum gerelateerde functies */ // Voor serverside gebruik staan ze ook nog een keer in Shared\locale.inc var calendar_names = { 'NL' : { days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag", "zondag"], daysShort: ["Zon", "Maa", "Din", "Woe", "Don", "Vri", "Zat", "Zon"], daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"], monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], weekMin: 'wk' }, 'EN': { days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], weekMin: 'wk' }, 'DE' : { days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"], daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], weekMin: 'wo' }, 'FR' : { days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"], daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"], daysMin: ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa", "Di"], months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], monthsShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Jul", "Aoû", "Sep", "Oct", "Nov", "Déc"], weekMin: "se" }, 'NO' : { days: ["søndag", "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lørdag", "søndag"], daysShort: ["søn", "man", "tir", "ons", "tor", "fre", "lør", "søn"], daysMin: ["sø", "ma", "ti", "on", "to", "fe", "lø", "sø"], months: ["januar", "februar", "mars", "april", "mai", "juni", "juli", "august", "september", "oktober", "november", "desember"], monthsShort: ["jan", "feb", "mar", "apr", "mai", "jun", "jul", "aug", "sep", "okt", "nov", "dec"], weekMin: "uk" }, 'SV' : { days: ["söndag", "måndag", "tisdag", "onsdag", "torsdag", "fredag", "lördag", "söndag"], daysShort: ["sön", "mån", "tis", "ons", "tor", "fre", "lör", "sön"], daysMin: ["sö", "må", "ti", "on", "to", "fe", "lö", "sö"], months: ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"], monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"], weekMin: "vk" }, 'DA' : { days: ["søndag", "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lørdag", "søndag"], daysShort: ["søn", "man", "tir", "ons", "tor", "fre", "lør", "søn"], daysMin: ["sø", "ma", "ti", "on", "to", "fe", "lø", "sø"], months: ["januar", "februar", "marts", "april", "maj", "juni", "juli", "august", "september", "oktober", "november", "desember"], monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"], weekMin: "ug" }, 'FI' : { days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"], daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"], daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"], months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"], weekMin: "vi" } }[user_lang]; Date.prototype.midnight = function midnight() { var midn = new Date(this); midn.setHours(0); midn.setMinutes(0); midn.setSeconds(0); return midn; } function weeksInYear(year) { var X1, X2, NW with (X1=new Date(year, 0, 4)) setDate(getDate() - (6+getDay())%7) // first day of week 1 with (X2=new Date(year, 11, 28)) setDate(getDate() + (7-getDay())%7) // last day of week NW NW = Math.round((X2-X1)/(7*864e5)) // number of weeks in year return NW; } function getWnDow(d) { // ISO 8601 WkNo. m=1..12 if (!d) d = new Date(); var ms1d = 864e5; // milliseconds one day var ms7d = 7*ms1d; // miliseconds 7 days var DC3 = Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()+3)/ms1d; // An absolute day number var dayofweek = 1 + (DC3+7777777)%7; // Day of Week var AWN = Math.floor(DC3/7); // An absolute week number var Wyr = new Date(AWN*ms7d).getUTCFullYear(); var weeknr = AWN - Math.floor(Date.UTC(Wyr, 0, 0)/ms7d); return [weeknr, dayofweek ] } function getWeeknumber(d) { return getWnDow(d)[0]; } function getDayOfWeek(d) { return getWnDow(d)[1]; } function YWDtoDate(Y, W, D) { // ISO 8601 var d = new Date(Y, 0, 3) d.setDate( 3 - d.getDay() + (W-1) * 7 + D ) return d } function padout(number) { return (number < 10) ? '0' + number : number; } // This function should only be used to format display, // – never as part of a computation. function toTimeString(jsDate, bWithSeconds) { jsDate = new Date(jsDate.valueOf()+1); // rounding errors ret = padout(jsDate.getHours())+":"+padout(jsDate.getMinutes()); if (bWithSeconds) ret += ":"+padout(jsDate.getSeconds()); return ret; } function toDateString(jsDate) { return calendar_names.daysMin[jsDate.getDay()] + " " + padout(jsDate.getDate())+"-"+padout(jsDate.getMonth()+1)+"-"+padout(jsDate.getFullYear()) } function toDateTimeString(jsDate, bWithSeconds) { return toDateString(jsDate)+" "+toTimeString(jsDate, bWithSeconds) } Date.prototype.getFloatHours = function getFloatHours() { return this.getHours() + (this.getMinutes()/60); } // Noot: rondt af op res_h! // levert een nieuw date-object op Date.prototype.setFloatHours = function setFloatHours(hrs, res_h) { var dd = new Date(this); hrs = Math.floor((hrs/res_h)+0.5) * res_h; var hh = Math.floor(hrs); var mm = (hrs*60) % 60; dd.setHours(hh,mm,0,0); return dd; } // Noot: rondt af op res_h! // levert een nieuw date-object op Date.prototype.addFloatHours = function addFloatHours(hrs, res_h) { return this.setFloatHours(this.getFloatHours() + hrs, res_h); } function cal_checkVolgnr(fieldId, volgnr) { // Aangeroepen door de onChange van elke kalender om de volgorde in tijd van de kalenders te controleren // Alleen kalenders die een volgnummer hebben gekregen moeten worden gecontroleerd // calArray staat nu altijd op volgorde van volgnummer. // Controleer of kalender Kx niet na kalender Kx+1, Kx+2... komt. Toch het geval dan Kx+1, Kx+2... = Kx. // Controleer of kalender Kx niet voor kalender Kx-1, Kx-2... komt. Toch het geval dan Kx-1, Kx-2... = Kx. for (var i = 0; i < calArray.length; i++) { var fromdate = new Date(parseInt($("#" + fieldId).val())); // degene die de gebruiker net heeft gewijzigd // Als de gewijzigde kalender of de vergelijkende kalender een tijdsveld heeft dan ingevulde tijd ook meenemen. Anders 0 nemen. // Elke vergelijkende kalender vergelijken met de gewijzigde kalender. // Bij lege waarde is $("#time_from_" + XXX).timePickerGetTime() nul(0) en heeft als object dan geen getTime() functie. var timefromms = $("#time_from_" + fieldId).length > 0 && $("#time_from_" + fieldId).timePickerGetTime() > 0? $("#time_from_" + fieldId).timePickerGetTime().getTime() : 0; // Gewijzigd veld. var timetoms = $("#time_from_" + calArray[i].id).length > 0 && $("#time_from_" + calArray[i].id).timePickerGetTime() > 0? $("#time_from_" + calArray[i].id).timePickerGetTime().getTime() : 0; // Vergelijkend veld. // Kalender Kx vooruit gezet if (calArray[i].id != fieldId && calArray[i].volgnr > volgnr && ($("#" + calArray[i].id).val() != "") && parseInt($("#" + calArray[i].id).val()) < parseInt($("#" + fieldId).val())) { // Veld aanpassen (Veld is ingevuld) // Maak Kx+1, Kx+2... gelijk aan Kx $("#show_" + calArray[i].id).datepicker('setDate', fromdate); $("#show_" + calArray[i].id).val($("#show_" + fieldId).val()); // Is tijdveld wel aanwezig en is die niet leeg? if (timefromms > 0) { // Als de tijd van tx > tijd van tx+1, tx+2..., maak dan de tijden gelijk: tijd van tx+1, tx+2... = tijd van tx. if (timefromms > timetoms) { // Datum + tijd overnemen $("#" + calArray[i].id).val(fromdate.getTime()); // hidden timestamp $("#time_from_" + calArray[i].id).val($("#time_from_" + fieldId).val()); // Zichtbare tijd overnemen } else { // Datum overnemen, eigen tijd behouden var dt2 = fromdate.midnight(); dt2.setSeconds(timetoms / 1000); // setSeconds gaat goed om met zomertijd/wintertijd $("#" + calArray[i].id).val(dt2.getTime()); } } else { // Kalender Kx heeft geen tijdsveld. // Indien veld Kx+i wel een tijdsveld heeft, dan eigen tijd behouden. var value = fromdate.midnight().getTime() + ($("#time_from_" + calArray[i].id).length > 0 && $("#time_from_" + calArray[i].id).val() != "" // Heeft veld Kx+i een tijdsveld en is die niet leeg? ? timetoms // Tijdsveld is aanwezig en niet leeg. Dan kan ik met getTime() de tijd ophalen. : 0) // Tijdsveld is niet aanwezig. Dan nemen we voor de tijd 0. $("#" + calArray[i].id).val(value); } } // Kalender Kx achteruit gezet if (calArray[i].id != fieldId && calArray[i].volgnr < volgnr && ($("#" + calArray[i].id).val() != "") && parseInt($("#" + calArray[i].id).val()) > parseInt($("#" + fieldId).val())) { // Veld aanpassen (Veld is ingevuld) // Maak Kx-1, Kx-2... gelijk aan Kx $("#show_" + calArray[i].id).datepicker('setDate', fromdate); $("#show_" + calArray[i].id).val($("#show_" + fieldId).val()); // Is tijdveld wel aanwezig en is die niet leeg? if ($("#time_from_" + fieldId).length > 0 && $("#time_from_" + fieldId).val() != "" && $("#time_from_" + calArray[i].id).length > 0 && $("#time_from_" + calArray[i].id).val() != "") { // Als de tijd van tx < tijd van tx-1, tx-2..., maak dan de tijden gelijk: tijd van tx-1, tx-2... = tijd van tx. if (timefromms < timetoms) { // Datum + tijd overnemen $("#" + calArray[i].id).val(fromdate.getTime());// hidden timestamp $("#time_from_" + calArray[i].id).val($("#time_from_" + fieldId).val()); // Zichtbare tijd overnemen } else { // Datum overnemen, eigen tijd behouden var dt2 = fromdate.midnight(); dt2.setSeconds(timetoms / 1000); // setSeconds gaat goed om met zomertijd/wintertijd $("#" + calArray[i].id).val(dt2.getTime()); } } else { // Kalender Kx heeft geen tijdsveld. $("#" + calArray[i].id).val(fromdate.midnight().getTime()); } } } // Datums van de zichtbare kalenders staan goed maar de tijd kan nog eerder zijn dan voorafgaande // (zichtbare) datum (begindatumtijd > einddatumtijd). // Daarnaast eventueel de hidden datums/tijden aanpassen. // Werkt ook voor meer dan twee kalenders. var defaultvolgnr; for (var i = 0; i < calArray.length; i++) { // Bepaal volgnr van de eerste zichtbare datum. if ($("#" + calArray[i].id).closest("tr").css("display") != "none") { defaultvolgnr = i; var defaultdate = new Date(parseInt($("#" + calArray[defaultvolgnr].id).val())); break; } } for (var i = 0; i < calArray.length; i++) { // Vind de hidden datum velden. Deze moeten wellicht aangepast worden. if (defaultvolgnr == i) continue; if (($("#show_" + calArray[i].id).css("display") == "none" || $("#" + calArray[i].id).closest("tr").css("display") == "none") && ($("#show_" + calArray[i].id)[0].getAttribute("nofollow") == 0)) { // Datum is niet zichtbaar // Veld aanpassen if ($("#" + calArray[defaultvolgnr].id).val() == "") { // Zichtbare datumveld is leeg. Maak hidden datumveld ook leeg $("#show_" + calArray[i].id).val(""); $("#" + calArray[i].id).val(""); } else { // Maak datum van datumveld i gelijk aan zichtbare datum. // Tijd hidden kalender gelijk maken aan eerstvoorafgaande zichtbare kalender. Indien geen eerstvoorafgaande zichtbare kalender aanwezig dan eerstvolgende zichtbare kalender nemen $("#show_" + calArray[i].id).datepicker('setDate', defaultdate); $("#show_" + calArray[i].id).val($("#show_" + calArray[defaultvolgnr].id).val()); // Is tijdveld wel aanwezig en is die niet leeg? if ($("#time_from_" + calArray[i].id).length > 0 && $("#time_from_" + calArray[i].id).val() != "") { // Tijd veld is aanwezig en is gevuld. // Als ik de datum gelijk maak maar de tijd niet aanpas, is dan de begindatumtijd < einddatumtijd? var new_date_with_own_time = defaultdate.midnight(); new_date_with_own_time.setSeconds(timetoms/1000); if (defaultdate < new_date_with_own_time) { // Zichtbare datum is eerder (begindatumtijd < einddatumtijd), dan alleen datum aanpassen en de tijd niet (eigen tijd behouden) $("#" + calArray[i].id).val(new_date_with_own_time.getTime()); } else { // Zichtbare datum is later (begindatumtijd > einddatumtijd), dan datum en tijd gelijk zetten // Datum en tijd gelijk zetten. $("#" + calArray[i].id).val(defaultdate.midnight().setSeconds($("#time_from_" + calArray[defaultvolgnr].id).timePickerGetTime().getTime()/1000)); $("#time_from_" + calArray[i].id).val($("#time_from_" + calArray[defaultvolgnr].id).val()); } } } } else { // Datum is zichtbaar of nofollow = 1 // Datums zijn nu goed maar de tijd kan nog eerder zijn dan zichtbare datum (begindatumtijd > einddatumtijd) // Daarnaast moeten beide datums wel een waarde hebben en moet het tijdveld aanwezig zijn if (($("#" + calArray[defaultvolgnr].id).val() > $("#" + calArray[i].id).val()) && ($("#" + calArray[defaultvolgnr].id).val() != "" && $("#" + calArray[i].id).val() != "") && ($("#time_from_" + calArray[i].id).length > 0)) { // Zichtbare datum is eerder (begindatumtijd > einddatumtijd), deze zichtbare datum gelijk maken aan zichtbare datum // Tijd veld is aanwezig. Datum en tijd gelijk zetten. $("#" + calArray[i].id).val(defaultdate.midnight().getTime() + $("#time_from_" + calArray[defaultvolgnr].id).timePickerGetTime().getTime()); $("#time_from_" + calArray[i].id).val($("#time_from_" + calArray[defaultvolgnr].id).val()); } if ($("#" + calArray[i].id).val() != "") { defaultvolgnr = i;// eerstvoorafgaande zichtbare GEVULDE kalender is nu deze var defaultdate = new Date(parseInt($("#" + calArray[defaultvolgnr].id).val())); } } } } // te gebruiken in combinatie met FCLTCalender function cal_isVrijeDag(datum) { var nacht = datum.midnight(); return ($.inArray(nacht.getTime(), mld_vrije_dagen)> -1); } // te gebruiken in combinatie met FCLTCalender function cal_isWeekend(datum) { var dag = datum.getDay(); return (dag == 0 || dag == 6); // we ondersteunen geen andere weekenden } // Als veld door DatePicker is gewijzigd function cal_onChange(fieldID, params) { // Eventuele bad class verwijderen. Kan ontstaan door met de hand een verkeerde waarde/formaat in te vullen. Met datepicker altijd juiste waarde/formaat. $('#show_' + fieldID).removeClass('bad'); var dt = parseInt($('#'+fieldID).val()); // Er is een datum ingevuld m.b.v. de datepicker if ($("#time_from_" + fieldID).length > 0 && $("#time_from_" + fieldID).val() != "") { // De tijd bij de datum optellen indien er een tijd is ingevuld var dt2 = new Date(dt).midnight(); var tm = $("#time_from_"+fieldID).timePickerGetTime().getTime(); dt2.setSeconds(tm / 1000); // setSeconds gaat goed om met zomertijd/wintertijd $('#'+fieldID).val(dt2.getTime()); } if (params.volgnr) { cal_checkVolgnr(fieldID, params.volgnr); } if (params.onChange) { eval(params.onChange, (new Date(parseInt($('#'+fieldID).val())))); } if (params.onChangeDate) { eval(params.onChangeDate, (new Date(parseInt($('#'+fieldID).val())))); } } // Als veld door intikken is gewijzigd // zie ook sortable.js voor DATE_RE function cal_show_onChange(e) { $(this).removeClass('bad'); // negeer letters (dag) vooraan // sta toe 3 -> 3e van huidige maand en 3-2 -> 3 feb huidig jaar var DATE_RE = /^[a-zA-Z ]*(\d\d?)[\/\.\- ]?(\d\d?)?[\/\.\- ]?((\d\d)?\d\d)?$/; var dttxt = $(this).val(); var possdate = dttxt.match(DATE_RE); if (possdate && possdate.length) // er moet minstens iets goed zijn { var pYear, pMonth, pDay; if (possdate.length > 2 && possdate[3]) { var yr = parseInt(possdate[3],10); if (yr<100) yr += 2000; pYear = yr; } else pYear = new Date().getFullYear(); if (possdate.length > 1 && possdate[2]) { pMonth = parseInt(possdate[2], 10) - 1 } else pMonth = new Date().getMonth(); pDay = parseInt(possdate[1], 10); dt = new Date(pYear, pMonth, pDay); $(this).datepicker('setDate', dt); if ($(this)[0].onSelect) $(this)[0].onSelect.apply(); } else { if ($(this).val() == "") // Lege waarde mag $(this).datepicker('setDate'); // Zet de milliseconden datum op een lege waarde else $(this).addClass('bad'); } } // Als veld door intikken is gewijzigd function time_show_onChange(showfieldID, fieldID, params) { var zelf = $("#"+showfieldID); $("div.time-holder").hide(); zelf.removeClass('bad'); // sta toe 14 -> 14:00h // sta toe 930 -> 9:30h // sta ook allerlei separators toe. var TIME_RE = /^(\d*)[\/\.\-\: ]?(\d\d?)?$/; var tmtxt = zelf.val(); posstime = tmtxt.match(TIME_RE); if (posstime && posstime.length && !isNaN(parseInt(posstime, 10))) // er moet minstens iets goed zijn { var hh = parseInt(posstime, 10); mm = 0; if (posstime.length > 1 && posstime[2]) { var mm = parseInt(posstime[2],10); } else // 930 voor 9:30h if (hh > 100) { mm = hh % 100; hh = Math.floor(hh / 100); } hh = hh % 24; mm = mm % 60; // Opgeschoonde waarde opslaan zelf.val(String((hh<10?"0":"")+hh) + ":" + String((mm<10?"0":"")+mm), true); if ($('#'+fieldID).val() != "") { // Bepaal de milliseconden datum inclusief de tijd $('#'+fieldID).val(new Date(parseInt($('#'+fieldID).val())).midnight().getTime() + $("#"+showfieldID).timePickerGetTime().getTime()); } if (params.volgnr>=0) { cal_checkVolgnr(fieldID, params.volgnr); } } else { if (zelf.val() == "") // Lege waarde mag { if ($('#'+fieldID).val() != "") { // Neem de tijd niet mee om de milliseconden datum te zetten (Verminder de miliseconden datum met de tijd) $('#'+fieldID).val(new Date(parseInt($('#'+fieldID).val())).midnight().getTime()); } } else zelf.addClass('bad'); } if (params.onChange) { eval(params.onChange); } if (params.onChangeTime) { eval(params.onChangeTime); } }