mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-16 14:32:18 +00:00
275 lines
9.2 KiB
JavaScript
275 lines
9.2 KiB
JavaScript
import {user_locale} from "../plugin/Phrasen.js";
|
|
import CalendarDates from "./CalendarDates.js";
|
|
|
|
const monthDayRanges = []
|
|
for(let i = 1; i < 13; i++) {
|
|
monthDayRanges.push(new Date(new Date(Date.now()).getFullYear(), i, 0).getDate())
|
|
}
|
|
|
|
class CalendarDate {
|
|
constructor(y, m, d) {
|
|
this.weekStart = CalendarDate.getWeekStart();
|
|
this.watchLocale = Vue.watch(
|
|
user_locale,
|
|
(newLocale, oldLocale, onCleanup) =>{
|
|
this.weekStart = CalendarDate.getWeekStart();
|
|
this._clean();
|
|
onCleanup((cleanup)=>{
|
|
// do clean up
|
|
});
|
|
},
|
|
|
|
);
|
|
this.set(y, m, d);
|
|
this._clean();
|
|
CalendarDates.subscribe(this);
|
|
}
|
|
get y() { return this._y }
|
|
set y(v) { this._y = v; this._clean() }
|
|
get m() { return this._m }
|
|
set m(v) { this._m = v; this._clean() }
|
|
get d() { return this._d }
|
|
set d(v) { this._d = v; this._clean() }
|
|
/**
|
|
* @see https://www.smart-rechner.de/kalenderwochen/rechner.php
|
|
*/
|
|
get w() {
|
|
if (this._w === null) {
|
|
if (this.weekStart == 1 && this._m == 11 && this._d > 28 && this.wd <= this._d-29) {
|
|
this._w = 1;
|
|
} else if (this.weekStart == 1 && this._m == 0 && this._d < 4 && 3-this.wd <= -this._d) {
|
|
let weekStartOfTheYear = new Date(this.y-1, 0, this.weekStart == 1 ? 4 : 1);
|
|
weekStartOfTheYear.setDate(weekStartOfTheYear.getDate() - (weekStartOfTheYear.getDay() + 7 - this.weekStart)%7);
|
|
this._w = Math.ceil((Math.floor((new Date(this.y, this.m, this.d) - weekStartOfTheYear) / 86400000) + 1) / 7);
|
|
} else {
|
|
let weekStartOfTheYear = new Date(this.y, 0, this.weekStart == 1 ? 4 : 1);
|
|
weekStartOfTheYear.setDate(weekStartOfTheYear.getDate() - (weekStartOfTheYear.getDay() + 7 - this.weekStart)%7);
|
|
this._w = Math.ceil((Math.floor((new Date(this.y, this.m, this.d) - weekStartOfTheYear) / 86400000) + 1) / 7);
|
|
}
|
|
}
|
|
return this._w;
|
|
}
|
|
set w(v) {
|
|
if (this.w != v) {
|
|
let lw = this.numWeeks;
|
|
|
|
this.d += (v - this.w) * 7;
|
|
|
|
if (v > 0 && v <= lw && this.w != v) {
|
|
if (this.weekStart != 1) {
|
|
if (this.w == 1) {
|
|
this.set(this.firstDayOfWeek);
|
|
} else {
|
|
this.set(this.lastDayOfWeek);
|
|
}
|
|
}
|
|
if (this.w != v) {
|
|
console.error('couldn\'t set the week', this, v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
get wYear() {
|
|
if( this.w === 1 ) {
|
|
return this.cdLastDayOfWeek.y;
|
|
}
|
|
return this.cdFirstDayOfWeek.y;
|
|
}
|
|
get wd() {
|
|
if (this._wd === null) {
|
|
// the .getDay() method from js Date object ALWAYS returns values from 0 to 6, where 0 is Sunday and 6 is Saturday
|
|
// aligns the getDay() result of the Date to the weekStart of the CalendarDate
|
|
this._wd = ((new Date(this.y, this.m, this.d)).getDay()+7-this.weekStart)%7;
|
|
}
|
|
return this._wd;
|
|
}
|
|
get firstDayOfWeek() {
|
|
let firstDayOfWeek = new Date(this.y, this.m, this.d);
|
|
// to ensure that firstDayOfWeek.getDay() is always greater than this.weekStart we add 7 and wrap the result around with %7 to avoid negative numbers
|
|
firstDayOfWeek.setDate(this.d -(firstDayOfWeek.getDay()+7-this.weekStart)%7);
|
|
return firstDayOfWeek;
|
|
}
|
|
get cdFirstDayOfWeek() {
|
|
let FirstDayOfWeek = new CalendarDate(this.firstDayOfWeek);
|
|
return FirstDayOfWeek;
|
|
}
|
|
get lastDayOfWeek() {
|
|
let lastDayOfWeek = new Date(this.y, this.m, this.d);
|
|
// uses the calculation from firstDayOfWeek and adds 6 days to the result to get the last day of the week
|
|
lastDayOfWeek.setDate(this.d -(lastDayOfWeek.getDay()+7-this.weekStart)%7 +6);
|
|
return lastDayOfWeek;
|
|
}
|
|
get wholeWorkWeek() {
|
|
const days = []
|
|
const date = new Date(this.y, this.m, this.d);
|
|
for(let i = 0; i < 5; i++) {
|
|
days[i] = new Date(this.y, this.m, this.d)
|
|
days[i].setDate(this.d -(date.getDay()+7-this.weekStart)%7 + i)
|
|
}
|
|
return days
|
|
}
|
|
get cdLastDayOfWeek() {
|
|
let LastDayOfWeek = new CalendarDate(this.lastDayOfWeek);
|
|
return LastDayOfWeek;
|
|
}
|
|
get firstDayOfCalendarMonth() {
|
|
let firstDayOfMonth = new Date(this.y, this.m, 1);
|
|
let offset = (firstDayOfMonth.getDay() + 7 - this.weekStart) % 7;
|
|
// offset will be greater than 1 most of the time, using a negative number for a date returns a date in the past
|
|
return new Date(this.y, this.m, 1-offset);
|
|
}
|
|
get cdFirstDayOfCalendarMonth() {
|
|
let firstDayOfMonth = new Date(this.y, this.m, 1);
|
|
let offset = (firstDayOfMonth.getDay() + 7 - this.weekStart) % 7;
|
|
let FirstDayOfCalendarMonth = new CalendarDate(this.y, this.m, 1 - offset);
|
|
return FirstDayOfCalendarMonth;
|
|
}
|
|
get lastDayOfCalendarMonth() {
|
|
// In JavaScript, the Date constructor interprets: A day of 0 as the last day of the previous month
|
|
let lastDayOfMonth = new Date(this.y, this.m+1, 0);
|
|
let offset = (lastDayOfMonth.getDay() + 7 - this.weekStart) % 7;
|
|
return new Date(lastDayOfMonth.getFullYear(), lastDayOfMonth.getMonth(), lastDayOfMonth.getDate()+6-offset);
|
|
}
|
|
get cdLastDayOfCalendarMonth() {
|
|
let lastDayOfMonth = new Date(this.y, this.m+1, 0);
|
|
let offset = (lastDayOfMonth.getDay() + 7 - this.weekStart) % 7;
|
|
let LasyDayOfCalendarMonth = new CalendarDate(lastDayOfMonth.getFullYear(), lastDayOfMonth.getMonth(), lastDayOfMonth.getDate() + 6 - offset);
|
|
return LasyDayOfCalendarMonth;
|
|
}
|
|
get cdLastDayOfNextCalendarMonth() {
|
|
let lastDayOfMonth = new Date(this.y, this.m+1, 0);
|
|
let offset = (lastDayOfMonth.getDay() + 7 - this.weekStart) % 7;
|
|
let LastDayOfNextCalendarMonth = new CalendarDate(lastDayOfMonth.getFullYear(), lastDayOfMonth.getMonth() + 1, lastDayOfMonth.getDate() + 6 - offset);
|
|
return LastDayOfNextCalendarMonth;
|
|
}
|
|
get nextSevenDays() {
|
|
const days = []
|
|
|
|
for(let i = 0; i < 7; i++) {
|
|
days[i] = new Date(this.y, this.m, this.d + i)
|
|
}
|
|
return days
|
|
}
|
|
get numWeeks() {
|
|
// if the week starts with Monday we have to go 3 days in the past from the start of the next year to get the correct numWeek of the current year
|
|
// this is because for example 30.12.2024 - 05.01.2025 is the first calendarWeek of 2025
|
|
let lastCalendarWeek = new CalendarDate(this.y + 1, 0, this.weekStart == 1 ? -3 : 0);
|
|
return lastCalendarWeek.w;
|
|
}
|
|
set(y,m,d,noClean) {
|
|
|
|
if (y !== undefined && (m === undefined || m === true) && d === undefined) {
|
|
if (this.isDate(y))
|
|
{
|
|
// set year/month/day from date object
|
|
return this.set(y.getFullYear(), y.getMonth(), y.getDate(), m);
|
|
}
|
|
if (y.y !== undefined && y.m !== undefined && y.d !== undefined)
|
|
{
|
|
// set year/month/day from CalendarDate object
|
|
return this.set(y.y, y.m, y.d, m);
|
|
}
|
|
}
|
|
// initialize year/month/day
|
|
this._y = y ?? 0;
|
|
this._m = m ?? 0;
|
|
this._d = d ?? 0;
|
|
|
|
if (!noClean)
|
|
this._clean();
|
|
}
|
|
_clean() {
|
|
this.set(new Date(this._y, this._m, this._d), true);
|
|
this._w = null;
|
|
this._wd = null;
|
|
}
|
|
format(options, lang=undefined) {
|
|
return (new Date(this._y, this._m, this._d)).toLocaleString(lang, options);
|
|
}
|
|
compare(d) {
|
|
if (this.isDate(d))
|
|
return (this.y === d.getFullYear() && this.m === d.getMonth() && this.d === d.getDate());
|
|
return (this.y === d.y && this.m === d.m && this.d === d.d);
|
|
}
|
|
isInWeek(w, y) {
|
|
if (this.y == y && this.w == w)
|
|
return true;
|
|
if (this.weekStart == 1)
|
|
return false;
|
|
let edgeDay = this.cdFirstDayOfWeek;console.log(edgeDay);
|
|
if (edgeDay.y == y && edgeDay.w == w)
|
|
return true;
|
|
edgeDay = this.cdLastDayOfWeek;
|
|
if (edgeDay.y == y && edgeDay.w == w)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
setLocale(locale) {
|
|
this.weekStart = CalendarDate.getWeekStart(locale);
|
|
}
|
|
// method that checks if the parameter is of type Date
|
|
isDate(obj){
|
|
return Object.prototype.toString.call(obj) === '[object Date]';
|
|
}
|
|
cleanup(){
|
|
if(this.watchLocale && this.watchLocale.stop) this.watchLocale.stop(); // TODO: ?
|
|
}
|
|
moveMonthInDirection (dir) {
|
|
// avoid setting date in wrong month if we try to create a date which does not exist like 30th of february
|
|
const newM = this.m + dir
|
|
const maxDaysTarget = monthDayRanges[newM]
|
|
|
|
if (this.d > maxDaysTarget) this.d = maxDaysTarget
|
|
|
|
this.m = newM // calls _clean which sets a new Date
|
|
}
|
|
}
|
|
/**
|
|
* Returns the weekday number (Date.getDay()) on which the week starts depending on the locale.
|
|
* This can be Saturday(6), Sunday(0) or Monday(1)
|
|
*
|
|
* @see https://stackoverflow.com/questions/53382465/how-can-i-determine-if-week-starts-on-monday-or-sunday-based-on-locale-in-pure-j
|
|
*
|
|
* @param string locale
|
|
*
|
|
* @return integer
|
|
*/
|
|
CalendarDate.getWeekStart = function(locale) {
|
|
|
|
locale = user_locale.value || locale || navigator.language;
|
|
const parts = locale.match(/^([a-z]{2,3})(?:-([a-z]{3})(?=$|-))?(?:-([a-z]{4})(?=$|-))?(?:-([a-z]{2}|\d{3})(?=$|-))?/i);
|
|
|
|
const language_code = parts[1];
|
|
const language_starting_Sat = ['ar','arq','arz','fa'];
|
|
const language_starting_Sun = 'amasbndzengnguhehiidjajvkmknkolomhmlmrmtmyneomorpapssdsmsnsutatethtnurzhzu'.match(/../g);
|
|
|
|
const region_code = parts[4];
|
|
const region_starting_Sat = 'AEAFBHDJDZEGIQIRJOKWLYOMQASDSY'.match(/../g);
|
|
const region_starting_Sun = 'AGARASAUBDBRBSBTBWBZCACNCODMDOETGTGUHKHNIDILINJMJPKEKHKRLAMHMMMOMTMXMZNINPPAPEPHPKPRPTPYSASGSVTHTTTWUMUSVEVIWSYEZAZW'.match(/../g);
|
|
|
|
if (region_code){
|
|
if (region_starting_Sun.includes(region_code))
|
|
return 0;
|
|
else if (region_starting_Sat.includes(region_code))
|
|
return 6;
|
|
else
|
|
return 1;
|
|
}
|
|
else if(language_code)
|
|
{
|
|
if (language_starting_Sun.includes(language_code))
|
|
return 0;
|
|
else if (language_starting_Sat.includes(language_code))
|
|
return 6;
|
|
else
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
export default CalendarDate
|