| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- import { ParsedOptions, Frequency } from './types'
- import { pymod, divmod, empty, includes } from './helpers'
- import { getWeekday, MAXYEAR, monthRange } from './dateutil'
- export class Time {
- public hour: number
- public minute: number
- public second: number
- public millisecond: number
- constructor(
- hour: number,
- minute: number,
- second: number,
- millisecond: number
- ) {
- this.hour = hour
- this.minute = minute
- this.second = second
- this.millisecond = millisecond || 0
- }
- getHours() {
- return this.hour
- }
- getMinutes() {
- return this.minute
- }
- getSeconds() {
- return this.second
- }
- getMilliseconds() {
- return this.millisecond
- }
- getTime() {
- return (
- (this.hour * 60 * 60 + this.minute * 60 + this.second) * 1000 +
- this.millisecond
- )
- }
- }
- export class DateTime extends Time {
- public day: number
- public month: number
- public year: number
- static fromDate(date: Date) {
- return new this(
- date.getUTCFullYear(),
- date.getUTCMonth() + 1,
- date.getUTCDate(),
- date.getUTCHours(),
- date.getUTCMinutes(),
- date.getUTCSeconds(),
- date.valueOf() % 1000
- )
- }
- constructor(
- year: number,
- month: number,
- day: number,
- hour: number,
- minute: number,
- second: number,
- millisecond: number
- ) {
- super(hour, minute, second, millisecond)
- this.year = year
- this.month = month
- this.day = day
- }
- getWeekday() {
- return getWeekday(new Date(this.getTime()))
- }
- getTime() {
- return new Date(
- Date.UTC(
- this.year,
- this.month - 1,
- this.day,
- this.hour,
- this.minute,
- this.second,
- this.millisecond
- )
- ).getTime()
- }
- getDay() {
- return this.day
- }
- getMonth() {
- return this.month
- }
- getYear() {
- return this.year
- }
- public addYears(years: number) {
- this.year += years
- }
- public addMonths(months: number) {
- this.month += months
- if (this.month > 12) {
- const yearDiv = Math.floor(this.month / 12)
- const monthMod = pymod(this.month, 12)
- this.month = monthMod
- this.year += yearDiv
- if (this.month === 0) {
- this.month = 12
- --this.year
- }
- }
- }
- public addWeekly(days: number, wkst: number) {
- if (wkst > this.getWeekday()) {
- this.day += -(this.getWeekday() + 1 + (6 - wkst)) + days * 7
- } else {
- this.day += -(this.getWeekday() - wkst) + days * 7
- }
- this.fixDay()
- }
- public addDaily(days: number) {
- this.day += days
- this.fixDay()
- }
- public addHours(hours: number, filtered: boolean, byhour: number[]) {
- if (filtered) {
- // Jump to one iteration before next day
- this.hour += Math.floor((23 - this.hour) / hours) * hours
- }
- for (;;) {
- this.hour += hours
- const { div: dayDiv, mod: hourMod } = divmod(this.hour, 24)
- if (dayDiv) {
- this.hour = hourMod
- this.addDaily(dayDiv)
- }
- if (empty(byhour) || includes(byhour, this.hour)) break
- }
- }
- public addMinutes(
- minutes: number,
- filtered: boolean,
- byhour: number[],
- byminute: number[]
- ) {
- if (filtered) {
- // Jump to one iteration before next day
- this.minute +=
- Math.floor((1439 - (this.hour * 60 + this.minute)) / minutes) * minutes
- }
- for (;;) {
- this.minute += minutes
- const { div: hourDiv, mod: minuteMod } = divmod(this.minute, 60)
- if (hourDiv) {
- this.minute = minuteMod
- this.addHours(hourDiv, false, byhour)
- }
- if (
- (empty(byhour) || includes(byhour, this.hour)) &&
- (empty(byminute) || includes(byminute, this.minute))
- ) {
- break
- }
- }
- }
- public addSeconds(
- seconds: number,
- filtered: boolean,
- byhour: number[],
- byminute: number[],
- bysecond: number[]
- ) {
- if (filtered) {
- // Jump to one iteration before next day
- this.second +=
- Math.floor(
- (86399 - (this.hour * 3600 + this.minute * 60 + this.second)) /
- seconds
- ) * seconds
- }
- for (;;) {
- this.second += seconds
- const { div: minuteDiv, mod: secondMod } = divmod(this.second, 60)
- if (minuteDiv) {
- this.second = secondMod
- this.addMinutes(minuteDiv, false, byhour, byminute)
- }
- if (
- (empty(byhour) || includes(byhour, this.hour)) &&
- (empty(byminute) || includes(byminute, this.minute)) &&
- (empty(bysecond) || includes(bysecond, this.second))
- ) {
- break
- }
- }
- }
- public fixDay() {
- if (this.day <= 28) {
- return
- }
- let daysinmonth = monthRange(this.year, this.month - 1)[1]
- if (this.day <= daysinmonth) {
- return
- }
- while (this.day > daysinmonth) {
- this.day -= daysinmonth
- ++this.month
- if (this.month === 13) {
- this.month = 1
- ++this.year
- if (this.year > MAXYEAR) {
- return
- }
- }
- daysinmonth = monthRange(this.year, this.month - 1)[1]
- }
- }
- public add(options: ParsedOptions, filtered: boolean) {
- const { freq, interval, wkst, byhour, byminute, bysecond } = options
- switch (freq) {
- case Frequency.YEARLY:
- return this.addYears(interval)
- case Frequency.MONTHLY:
- return this.addMonths(interval)
- case Frequency.WEEKLY:
- return this.addWeekly(interval, wkst)
- case Frequency.DAILY:
- return this.addDaily(interval)
- case Frequency.HOURLY:
- return this.addHours(interval, filtered, byhour)
- case Frequency.MINUTELY:
- return this.addMinutes(interval, filtered, byhour, byminute)
- case Frequency.SECONDLY:
- return this.addSeconds(interval, filtered, byhour, byminute, bysecond)
- }
- }
- }
|