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