Skip to content

Commit

Permalink
Merge branch 'cleanup-refactor'
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgoli committed Dec 4, 2018
2 parents b4be905 + 643791d commit c839d54
Show file tree
Hide file tree
Showing 18 changed files with 978 additions and 639 deletions.
2 changes: 1 addition & 1 deletion src/callbackiterresult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type Iterator = (d: Date, len: number) => boolean
* IterResult subclass that calls a callback function on each add,
* and stops iterating when the callback returns false.
*/
export default class CallbackIterResult extends IterResult {
export default class CallbackIterResult extends IterResult<'all' | 'between'> {
private iterator: Iterator

constructor (
Expand Down
250 changes: 250 additions & 0 deletions src/datetime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import { ParsedOptions, Frequency } from './types'
import { pymod, divmod, empty, includes } from './helpers'
import { dateutil } 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 dateutil.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
}

while (true) {
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
}

while (true) {
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
}

while (true) {
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 = dateutil.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 > dateutil.MAXYEAR) {
return
}
}

daysinmonth = dateutil.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)
}
}
}
Loading

0 comments on commit c839d54

Please sign in to comment.