Skip to content

Commit 75a4716

Browse files
committed
Merge branch 'danfo/typescript' of https://github.com/javascriptdata/danfojs into danfo/typescript
2 parents b1f0c42 + d9f0ee6 commit 75a4716

7 files changed

Lines changed: 436 additions & 2 deletions

File tree

src/danfojs-base/aggregators/groupby.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { Console } from "console";
21
import DataFrame from "../core/frame"
32
import { ArrayType1D, ArrayType2D } from "../shared/types"
43
import { variance, std, median, mode, mean } from 'mathjs';
5-
import Utils from "../shared/utils";
64
import concat from "../transformers/concat"
75
import Series from "../core/series";
86

src/danfojs-base/core/daterange.ts

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

src/danfojs-base/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import OneHotEncoder from "./transformers/encoders/one.hot.encoder";
2626
import getDummies from "./transformers/encoders/dummy.encoder"
2727
import concat from "./transformers/concat"
2828
import merge from "./transformers/merge"
29+
import date_range from "./core/daterange"
2930

3031
const __version = "1.0.0"
3132

@@ -45,5 +46,6 @@ export {
4546
getDummies,
4647
concat,
4748
merge,
49+
date_range,
4850
__version,
4951
}

src/danfojs-browser/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
concat,
2727
merge,
2828
toDateTime,
29+
date_range,
2930
__version,
3031
} from "../../danfojs-base";
3132

@@ -65,5 +66,6 @@ export {
6566
getDummies,
6667
concat,
6768
merge,
69+
date_range,
6870
__version,
6971
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
describe("dfd.date_range", function(){
2+
3+
// it("Obtain date between start and end specified", function(){
4+
// let d = dfd.date_range({start:'2018-04-24',end:'2018-04-27'})
5+
// let rslt = [
6+
// '4/24/2018, 1:00:00 AM',
7+
// '4/25/2018, 1:00:00 AM',
8+
// '4/26/2018, 1:00:00 AM',
9+
// '4/27/2018, 1:00:00 AM'
10+
// ]
11+
// assert.deepEqual(d,rslt)
12+
// });
13+
it("Obtain date between start with end not specified, but period and freq specified", function(){
14+
let d = dfd.date_range({ start:'1/1/2018', period:5, freq:'M' });
15+
let rslt = [
16+
'1/1/2018, 12:00:00 AM',
17+
'2/1/2018, 12:00:00 AM',
18+
'3/1/2018, 12:00:00 AM',
19+
'4/1/2018, 12:00:00 AM',
20+
'5/1/2018, 12:00:00 AM'
21+
];
22+
assert.deepEqual(d, rslt);
23+
});
24+
it("Obtain date between start with end not specified, but period and freq specified, plus offset", function(){
25+
let d = dfd.date_range({ start:'1/1/2018', period:5, freq:'3M' });
26+
let rslt = [
27+
'1/1/2018, 12:00:00 AM',
28+
'4/1/2018, 12:00:00 AM',
29+
'7/1/2018, 12:00:00 AM',
30+
'10/1/2018, 12:00:00 AM',
31+
'1/1/2019, 12:00:00 AM'
32+
];
33+
assert.deepEqual(d, rslt);
34+
});
35+
it("Obtain date between start with end not specified, but period and freq specified, plus offset, longer freq", function(){
36+
let d = dfd.date_range({ start:'1/1/2018', period:5, freq:'35m' });
37+
let rslt = [
38+
"1/1/2018, 12:00:00 AM",
39+
"1/1/2018, 12:35:00 AM",
40+
"1/1/2018, 1:10:00 AM",
41+
"1/1/2018, 1:45:00 AM",
42+
"1/1/2018, 2:20:00 AM"
43+
];
44+
assert.deepEqual(d, rslt);
45+
});
46+
it("Obtain date range with start not specified but end and period is given", function(){
47+
let d = dfd.date_range({ end:'1/1/2018', period:8 });
48+
let rslt = [
49+
'12/25/2017, 12:00:00 AM',
50+
'12/26/2017, 12:00:00 AM',
51+
'12/27/2017, 12:00:00 AM',
52+
'12/28/2017, 12:00:00 AM',
53+
'12/29/2017, 12:00:00 AM',
54+
'12/30/2017, 12:00:00 AM',
55+
'12/31/2017, 12:00:00 AM',
56+
'1/1/2018, 12:00:00 AM'
57+
];
58+
assert.deepEqual(d, rslt);
59+
});
60+
it("inputing wrong freq", function(){
61+
assert.throws(function () { dfd.date_range({ end:'1/1/2018', period:8, freq:"d" }); }, Error, 'invalid freq d');
62+
});
63+
it("inputing wrong freq with offset", function(){
64+
assert.throws(function () { dfd.date_range({ end:'1/1/2018', period:8, freq:"4d" }); }, Error, 'invalid freq d');
65+
});
66+
it("inputing wrong freq offset", function(){
67+
assert.throws(function () { dfd.date_range({ end:'1/1/2018', period:8, freq:"abcm" }); }, Error, 'invalid freq offset abc');
68+
});
69+
// it("Obtain date between start and end specified with different month", function(){
70+
71+
// let d = dfd.date_range({start:'2018-04-24',end:'2018-05-27'})
72+
// let rslt = [
73+
// '4/24/2018, 1:00:00 AM',
74+
// '4/25/2018, 1:00:00 AM',
75+
// '4/26/2018, 1:00:00 AM',
76+
// '4/27/2018, 1:00:00 AM',
77+
// '4/28/2018, 1:00:00 AM',
78+
// '4/29/2018, 1:00:00 AM',
79+
// '4/30/2018, 1:00:00 AM',
80+
// '5/1/2018, 1:00:00 AM',
81+
// '5/2/2018, 1:00:00 AM',
82+
// '5/3/2018, 1:00:00 AM',
83+
// '5/27/2018, 1:00:00 AM'
84+
// ]
85+
// assert.deepEqual(d,rslt)
86+
// });
87+
});

src/danfojs-node/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
concat,
2727
merge,
2828
toDateTime,
29+
date_range,
2930
__version
3031
} from "../../danfojs-base";
3132
import {
@@ -72,5 +73,6 @@ export {
7273
getDummies,
7374
concat,
7475
merge,
76+
date_range,
7577
__version
7678
}

0 commit comments

Comments
 (0)