File: D:/web/matomo.circ/plugins/CoreHome/vue/src/Periods/Range.ts
/*!
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
import { translate } from '../translate';
import Periods from './Periods';
import {
parseDate,
format,
getToday,
todayIsInRange,
} from './utilities';
export default class RangePeriod {
constructor(
public readonly startDate: Date,
public readonly endDate: Date,
public readonly childPeriodType: string,
) {}
/**
* Returns a range representing the last N childPeriodType periods, including the current one.
*/
static getLastNRange(
childPeriodType: string,
strAmount: string|number,
strEndDate?: Date|string,
): RangePeriod {
const nAmount = Math.max(parseInt(strAmount.toString(), 10) - 1, 0);
if (Number.isNaN(nAmount)) {
throw new Error('Invalid range strAmount');
}
let endDate = strEndDate ? parseDate(strEndDate) : getToday();
let startDate = new Date(endDate.getTime());
if (childPeriodType === 'day') {
startDate.setDate(startDate.getDate() - nAmount);
} else if (childPeriodType === 'week') {
startDate.setDate(startDate.getDate() - (nAmount * 7));
} else if (childPeriodType === 'month') {
startDate.setDate(1);
startDate.setMonth(startDate.getMonth() - nAmount);
} else if (childPeriodType === 'year') {
startDate.setFullYear(startDate.getFullYear() - nAmount);
} else {
throw new Error(`Unknown period type '${childPeriodType}'.`);
}
if (childPeriodType !== 'day') {
const startPeriod = Periods.periods[childPeriodType].parse(startDate);
const endPeriod = Periods.periods[childPeriodType].parse(endDate);
[startDate] = startPeriod.getDateRange();
[, endDate] = endPeriod.getDateRange();
}
const firstWebsiteDate = new Date(1991, 7, 6);
if (startDate.getTime() - firstWebsiteDate.getTime() < 0) {
switch (childPeriodType) {
case 'year':
startDate = new Date(1992, 0, 1);
break;
case 'month':
startDate = new Date(1991, 8, 1);
break;
case 'week':
startDate = new Date(1991, 8, 12);
break;
case 'day':
default:
startDate = firstWebsiteDate;
break;
}
}
return new RangePeriod(startDate, endDate, childPeriodType);
}
/**
* Returns a range representing a specific child date range counted back from the end date
*
* @param childPeriodType Type of the period, eg. day, week, year
* @param rangeEndDate
* @param countBack Return only the child date range for this specific period number
* @returns {RangePeriod}
*/
static getLastNRangeChild(
childPeriodType: string,
rangeEndDate: Date|string,
countBack: number,
): RangePeriod {
const ed = rangeEndDate ? parseDate(rangeEndDate) : getToday();
let startDate = new Date(ed.getTime());
let endDate = new Date(ed.getTime());
if (childPeriodType === 'day') {
startDate.setDate(startDate.getDate() - countBack);
endDate.setDate(endDate.getDate() - countBack);
} else if (childPeriodType === 'week') {
startDate.setDate(startDate.getDate() - (countBack * 7));
endDate.setDate(endDate.getDate() - (countBack * 7));
} else if (childPeriodType === 'month') {
startDate.setDate(1);
startDate.setMonth(startDate.getMonth() - countBack);
endDate.setDate(1);
endDate.setMonth(endDate.getMonth() - countBack);
} else if (childPeriodType === 'year') {
startDate.setFullYear(startDate.getFullYear() - countBack);
endDate.setFullYear(endDate.getFullYear() - countBack);
} else {
throw new Error(`Unknown period type '${childPeriodType}'.`);
}
if (childPeriodType !== 'day') {
const startPeriod = Periods.periods[childPeriodType].parse(startDate);
const endPeriod = Periods.periods[childPeriodType].parse(endDate);
[startDate] = startPeriod.getDateRange();
[, endDate] = endPeriod.getDateRange();
}
const firstWebsiteDate = new Date(1991, 7, 6);
if (startDate.getTime() - firstWebsiteDate.getTime() < 0) {
switch (childPeriodType) {
case 'year':
startDate = new Date(1992, 0, 1);
break;
case 'month':
startDate = new Date(1991, 8, 1);
break;
case 'week':
startDate = new Date(1991, 8, 12);
break;
case 'day':
default:
startDate = firstWebsiteDate;
break;
}
}
return new RangePeriod(startDate, endDate, childPeriodType);
}
static parse(strDate: string, childPeriodType = 'day'): RangePeriod {
if (/^previous/.test(strDate)) {
const endDate = RangePeriod.getLastNRange(childPeriodType, '2').startDate;
return RangePeriod.getLastNRange(childPeriodType, strDate.substring(8), endDate);
}
if (/^last/.test(strDate)) {
return RangePeriod.getLastNRange(childPeriodType, strDate.substring(4));
}
const parts = decodeURIComponent(strDate).split(',');
return new RangePeriod(parseDate(parts[0]), parseDate(parts[1]), childPeriodType);
}
static getDisplayText(): string {
return translate('General_DateRangeInPeriodList');
}
getPrettyString(): string {
const start = format(this.startDate);
const end = format(this.endDate);
return translate('General_DateRangeFromTo', [start, end]);
}
getDateRange(): Date[] {
return [this.startDate, this.endDate];
}
containsToday(): boolean {
return todayIsInRange(this.getDateRange());
}
getDayCount(): number {
return (Math.ceil((this.endDate.getTime() - this.startDate.getTime()) / (1000 * 3600 * 24))
+ 1);
}
}
Periods.addCustomPeriod('range', RangePeriod);