@@ -63,7 +63,28 @@ class Resolution(object):
63
63
RESO_SEC : 'second' ,
64
64
RESO_MIN : 'minute' ,
65
65
RESO_HR : 'hour' ,
66
- RESO_DAY : 'day' }
66
+ RESO_DAY : 'day'
67
+ }
68
+
69
+ # factor to multiply a value by to convert it to the next finer grained
70
+ # resolution
71
+ _reso_mult_map = {
72
+ RESO_US : None ,
73
+ RESO_MS : 1000 ,
74
+ RESO_SEC : 1000 ,
75
+ RESO_MIN : 60 ,
76
+ RESO_HR : 60 ,
77
+ RESO_DAY : 24
78
+ }
79
+
80
+ _reso_str_bump_map = {
81
+ 'D' : 'H' ,
82
+ 'H' : 'T' ,
83
+ 'T' : 'S' ,
84
+ 'S' : 'L' ,
85
+ 'L' : 'U' ,
86
+ 'U' : None
87
+ }
67
88
68
89
_str_reso_map = dict ([(v , k ) for k , v in compat .iteritems (_reso_str_map )])
69
90
@@ -160,6 +181,34 @@ def get_reso_from_freq(cls, freq):
160
181
"""
161
182
return cls .get_reso (cls .get_str_from_freq (freq ))
162
183
184
+ @classmethod
185
+ def bump_to_int (cls , value , freq ):
186
+ """
187
+ Increase resolution an integer value is available to create an
188
+ offset.
189
+
190
+ Example
191
+ -------
192
+ >>> Resolution.bump_to_int(1.5, 'T')
193
+ <90 * Seconds>
194
+
195
+ >>> Resolution.bump_to_int(1.04, 'H')
196
+ <3744 * Seconds>
197
+
198
+ >>> Resolution.bump_to_int(1, 'D')
199
+ <Day>
200
+ """
201
+
202
+ if np .isclose (value % 1 , 0 ):
203
+ return int (value ), freq
204
+ else :
205
+ start_reso = cls .get_reso_from_freq (freq )
206
+ if start_reso == 0 :
207
+ raise ValueError (_CANNOT_CONVERT_TO_INT )
208
+ next_value = cls ._reso_mult_map [start_reso ] * value
209
+ next_name = cls ._reso_str_bump_map [freq ]
210
+ return cls .bump_to_int (next_value , next_name )
211
+
163
212
164
213
def get_to_timestamp_base (base ):
165
214
"""
@@ -384,6 +433,9 @@ def get_period_alias(offset_str):
384
433
385
434
386
435
_INVALID_FREQ_ERROR = "Invalid frequency: {0}"
436
+ _CANNOT_CONVERT_TO_INT = (
437
+ "Could not convert to integer offset at any resolution"
438
+ )
387
439
388
440
389
441
@deprecate_kwarg (old_arg_name = 'freqstr' , new_arg_name = 'freq' )
@@ -472,12 +524,17 @@ def to_offset(freq):
472
524
splitted [2 ::4 ]):
473
525
if sep != '' and not sep .isspace ():
474
526
raise ValueError ('separator must be spaces' )
475
- offset = get_offset (name )
527
+ prefix = _lite_rule_alias . get (name )
476
528
if stride_sign is None :
477
529
stride_sign = - 1 if stride .startswith ('-' ) else 1
478
530
if not stride :
479
531
stride = 1
532
+ if prefix in Resolution ._reso_str_bump_map .keys ():
533
+ stride , name = Resolution .bump_to_int (
534
+ float (stride ), prefix
535
+ )
480
536
stride = int (stride )
537
+ offset = get_offset (name )
481
538
offset = offset * int (np .fabs (stride ) * stride_sign )
482
539
if delta is None :
483
540
delta = offset
@@ -493,7 +550,9 @@ def to_offset(freq):
493
550
494
551
495
552
# hack to handle WOM-1MON
496
- opattern = re .compile (r'([\-]?\d*)\s*([A-Za-z]+([\-][\dA-Za-z\-]+)?)' )
553
+ opattern = re .compile (
554
+ r'([\-]?\d*|[\-]?\d*\.\d*)\s*([A-Za-z]+([\-][\dA-Za-z\-]+)?)'
555
+ )
497
556
498
557
499
558
def _base_and_stride (freqstr ):
0 commit comments