Skip to content

Commit 251f275

Browse files
committed
implement date_range
1 parent 0707618 commit 251f275

1 file changed

Lines changed: 235 additions & 0 deletions

File tree

src/danfojs-base/core/daterange.ts

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
import { ArrayType1D, ArrayType2D } from "../shared/types"
2+
import Utils from "../shared/utils";
3+
4+
const utils = new Utils();
5+
6+
interface Params {
7+
start?: string;
8+
offset?: number;
9+
end?: string;
10+
freq?: string;
11+
period?: number
12+
}
13+
export default class DateRange {
14+
private offset: number | undefined = null
15+
private start: string | undefined
16+
private end: string | undefined
17+
private freq: string | undefined
18+
private period: number | undefined
19+
private freqList: string[]
20+
21+
constructor(params: Params) {
22+
this.start = params.start
23+
this.end = params.end
24+
this.offset = params.offset
25+
this.freq = params.freq
26+
this.period = params.period
27+
this.freqList = [ "M", "D", "s", "H", "m", "Y" ]
28+
29+
if (this.freq.length == 1){
30+
if (!this.freqList.includes(this.freq)){
31+
throw new Error(`invalid freq ${this.freq}`);
32+
}
33+
} else {
34+
this.offset = parseInt(this.freq.slice(0, -1));
35+
if (!Number.isFinite(this.offset)){
36+
throw new Error(`invalid freq offset ${this.freq.slice(0, -1)}`);
37+
}
38+
this.freq = this.freq.slice(-1);
39+
if (!this.freqList.includes(this.freq)){
40+
throw new Error(`invalid freq ${this.freq}`);
41+
}
42+
}
43+
44+
45+
}
46+
47+
range({start, end, period, offset}: Params) {
48+
let startDate: Date
49+
let endDate: Date
50+
let startRange: number
51+
let endRange: number
52+
if (start && end) {
53+
startDate = new Date(start)
54+
startRange = this.freqType(startDate, this.freq)
55+
endDate = new Date(end)
56+
endRange = this.freqType(endDate, this.freq)
57+
58+
let startYear = startDate.getFullYear()
59+
let endYear = endDate.getFullYear()
60+
if ((startYear <= endYear) && (startDate.getMonth() !== endDate.getMonth())){
61+
if (this.freq == "M") {
62+
endRange = this.monthEnd(startDate, endDate)
63+
}
64+
else if (this.freq === "D") {
65+
endRange = this.dayEnd(startDate, endDate) - startRange
66+
}
67+
}
68+
let rangeArray = utils.range(startRange, endRange)
69+
if ( offset ) {
70+
rangeArray = this.offsetCount(rangeArray, offset)
71+
}
72+
let dateRange = rangeArray.map((x) => {
73+
return this.setDateProps(startDate, this.freq, x)
74+
})
75+
dateRange[dateRange.length -1] = endDate
76+
let dateString = this.toLocalString(dateRange)
77+
return dateString
78+
}
79+
else if ( start && !(end) ) {
80+
startDate = new Date(start)
81+
startRange = this.freqType(startDate, this.freq)
82+
endRange = offset ? ((period * offset) - 1) : period -1;
83+
84+
if ( startRange > endRange ) {
85+
endRange = endRange + startRange
86+
}
87+
let rangeArray = utils.range(startRange, endRange)
88+
89+
if ( offset ) {
90+
rangeArray = this.offsetCount(rangeArray, offset)
91+
}
92+
let dateRange = rangeArray.map((x) => {
93+
return this.setDateProps(startDate, this.freq, x)
94+
})
95+
96+
let dateString = this.toLocalString(dateRange)
97+
return dateString
98+
}
99+
else if (end && !(start)) {
100+
endDate = new Date(end)
101+
endRange = this.freqType(endDate, this.freq)
102+
startRange = (endRange - period) + 1
103+
let rangeArray = utils.range(startRange, endRange)
104+
105+
if ( offset ) {
106+
rangeArray = this.offsetCount(rangeArray, offset)
107+
}
108+
let dateRange = rangeArray.map((x) => {
109+
return this.setDateProps(endDate, this.freq, x)
110+
})
111+
let dateString = this.toLocalString(dateRange)
112+
return dateString
113+
}
114+
}
115+
116+
private freqType(date: Date, ftype: string): number{
117+
let rslt: number = null;
118+
switch (ftype){
119+
120+
case "M":
121+
rslt = date.getMonth();
122+
break;
123+
case "Y":
124+
rslt = date.getFullYear();
125+
break;
126+
case "s":
127+
rslt = date.getSeconds();
128+
break;
129+
case "D":
130+
rslt = date.getDate();
131+
break;
132+
case "H":
133+
rslt = date.getHours();
134+
break;
135+
case "m":
136+
rslt = date.getMinutes();
137+
break;
138+
}
139+
return rslt;
140+
}
141+
142+
143+
private offsetCount(dArray: number[], offset: number) :number[] {
144+
let rArray: number[] = []
145+
for (let i = 0; i < dArray.length; i += offset){
146+
rArray.push(dArray[i]);
147+
}
148+
return rArray;
149+
}
150+
151+
private setDateProps(date: Date, ftype: string, val: number[] | number): Date {
152+
let newDate = new Date(date.valueOf())
153+
switch (ftype){
154+
case "M":
155+
if (Array.isArray(val)){
156+
157+
newDate.setYear(newDate.getFullYear() + val[0]);
158+
newDate.setMonth(val[1]);
159+
} else {
160+
newDate.setMonth(val);
161+
}
162+
break;
163+
case "Y":
164+
newDate.setYear(val as number);
165+
break;
166+
case "s":
167+
newDate.setSeconds(val as number);
168+
break;
169+
case "D":
170+
newDate.setDate(val as number);
171+
break;
172+
case "H":
173+
newDate.setHours(val as number);
174+
break;
175+
case "m":
176+
newDate.setMinutes(val as number);
177+
break;
178+
}
179+
return newDate;
180+
}
181+
182+
183+
private toLocalString(dArray: Date[]) {
184+
let r_array = dArray.map((x) => {
185+
return x.toLocaleString();
186+
});
187+
return r_array;
188+
}
189+
190+
private monthEnd(startDate: Date, endDate: Date) {
191+
let endMonth = endDate.getMonth()
192+
let diffYear = endDate.getFullYear() - startDate.getFullYear()
193+
let endRange = (12 * diffYear) + endMonth
194+
return endRange
195+
}
196+
197+
private monthRange(range: number[]): number[][] {
198+
let minus: number;
199+
let yVal = 0
200+
let dateRange: number[][] = range.map((x) => {
201+
if (x > 11) {
202+
if ( x % 12 == 0) {
203+
minus = x
204+
yVal = x / 12
205+
return [yVal, (x - minus)]
206+
}
207+
else {
208+
return [yVal, (x -minus)]
209+
}
210+
}
211+
return [yVal, x]
212+
})
213+
return dateRange
214+
}
215+
216+
private dayEnd(startDate: Date, endDate: Date): number{
217+
let monthEnd = this.monthEnd(startDate, endDate)
218+
let range = utils.range(startDate.getMonth(), monthEnd)
219+
let mRange = this.monthRange(range)
220+
221+
let sum = 0
222+
for (let i=0; i < mRange.length; i++) {
223+
let val = mRange[i]
224+
let dDate: number
225+
if (i === mRange.length - 1) {
226+
dDate = new Date(startDate.getUTCFullYear() + val[0], val[1], endDate.getDate()).getDate()
227+
}
228+
else {
229+
dDate = new Date(startDate.getUTCFullYear() + val[0], val[1], 0).getDate()
230+
}
231+
sum += dDate
232+
}
233+
return sum
234+
}
235+
}

0 commit comments

Comments
 (0)