@@ -8,9 +8,10 @@ namespace Nest
88 [ JsonConverter ( typeof ( TimeJsonConverter ) ) ]
99 public class Time : IComparable < Time > , IEquatable < Time >
1010 {
11- private static readonly Regex _expressionRegex = new Regex ( @"^(?<factor>\d+(?:\.\d+)?)(?<interval>(?:y|M|w|d|h|m|s|ms))?$" , RegexOptions . Compiled | RegexOptions . ExplicitCapture ) ;
11+ private static readonly Regex _expressionRegex = new Regex ( @"^(?<factor>[-+]? \d+(?:\.\d+)?)(?<interval>(?:y|M|w|d|h|m|s|ms))?$" , RegexOptions . Compiled | RegexOptions . ExplicitCapture ) ;
1212
13- private static readonly double _year = TimeSpan . FromDays ( 365 ) . TotalMilliseconds ;
13+ private static readonly double _yearApproximate = TimeSpan . FromDays ( 365 ) . TotalMilliseconds ;
14+ private static readonly double _monthApproximate = TimeSpan . FromDays ( 30 ) . TotalMilliseconds ;
1415 private static readonly double _week = TimeSpan . FromDays ( 7 ) . TotalMilliseconds ;
1516 private static readonly double _day = TimeSpan . FromDays ( 1 ) . TotalMilliseconds ;
1617 private static readonly double _hour = TimeSpan . FromHours ( 1 ) . TotalMilliseconds ;
@@ -19,33 +20,15 @@ public class Time : IComparable<Time>, IEquatable<Time>
1920
2021 public double ? Factor { get ; private set ; }
2122 public TimeUnit ? Interval { get ; private set ; }
23+
24+ // TODO make nullable in 3.0
2225 public double Milliseconds { get ; private set ; }
26+ private double ApproximateMilliseconds { get ; set ; }
2327
2428 public static implicit operator Time ( TimeSpan span ) => new Time ( span ) ;
2529 public static implicit operator Time ( double milliseconds ) => new Time ( milliseconds ) ;
2630 public static implicit operator Time ( string expression ) => new Time ( expression ) ;
2731
28- public Time ( double factor , TimeUnit interval )
29- {
30- this . Factor = factor ;
31- this . Interval = interval ;
32-
33- if ( interval == TimeUnit . Year )
34- Milliseconds = ( long ) factor * _year ;
35- else if ( interval == TimeUnit . Week )
36- Milliseconds = ( long ) factor * _week ;
37- else if ( interval == TimeUnit . Day )
38- Milliseconds = ( long ) factor * _day ;
39- else if ( interval == TimeUnit . Hour )
40- Milliseconds = ( long ) factor * _hour ;
41- else if ( interval == TimeUnit . Minute )
42- Milliseconds = ( long ) factor * _minute ;
43- else if ( interval == TimeUnit . Second )
44- Milliseconds = ( long ) factor * _second ;
45- else //ms
46- Milliseconds = ( long ) factor ;
47- }
48-
4932 public Time ( TimeSpan timeSpan )
5033 {
5134 Reduce ( timeSpan . TotalMilliseconds ) ;
@@ -56,38 +39,36 @@ public Time(double milliseconds)
5639 Reduce ( milliseconds ) ;
5740 }
5841
42+ public Time ( double factor , TimeUnit interval )
43+ {
44+ this . Factor = factor ;
45+ this . Interval = interval ;
46+ SetMilliseconds ( this . Interval , this . Factor . Value ) ;
47+ }
48+
5949 public Time ( string timeUnit )
6050 {
6151 if ( timeUnit . IsNullOrEmpty ( ) ) throw new ArgumentException ( "Time expression string is empty" , nameof ( timeUnit ) ) ;
6252 var match = _expressionRegex . Match ( timeUnit ) ;
6353 if ( ! match . Success ) throw new ArgumentException ( $ "Time expression '{ timeUnit } ' string is invalid", nameof ( timeUnit ) ) ;
6454
6555 this . Factor = double . Parse ( match . Groups [ "factor" ] . Value , CultureInfo . InvariantCulture ) ;
66- this . Interval = match . Groups [ "interval" ] . Success
67- ? match . Groups [ "interval" ] . Value . ToEnum < TimeUnit > ( )
68- : TimeUnit . Millisecond ;
69-
70- if ( this . Interval == TimeUnit . Year )
71- Milliseconds = ( long ) ( this . Factor * _year ) ;
72- else if ( this . Interval == TimeUnit . Week )
73- Milliseconds = ( long ) ( this . Factor * _week ) ;
74- else if ( this . Interval == TimeUnit . Day )
75- Milliseconds = ( long ) ( this . Factor * _day ) ;
76- else if ( this . Interval == TimeUnit . Hour )
77- Milliseconds = ( long ) ( this . Factor * _hour ) ;
78- else if ( this . Interval == TimeUnit . Minute )
79- Milliseconds = ( long ) ( this . Factor * _minute ) ;
80- else if ( this . Interval == TimeUnit . Second )
81- Milliseconds = ( long ) ( this . Factor * _second ) ;
82- else //ms
83- Milliseconds = ( long ) this . Factor ;
56+
57+ if ( this . Factor > 0 )
58+ {
59+ this . Interval = match . Groups [ "interval" ] . Success
60+ ? match . Groups [ "interval" ] . Value . ToEnum < TimeUnit > ( StringComparison . Ordinal )
61+ : TimeUnit . Millisecond ;
62+ }
63+
64+ SetMilliseconds ( this . Interval , this . Factor . Value ) ;
8465 }
8566
8667 public int CompareTo ( Time other )
8768 {
8869 if ( other == null ) return 1 ;
89- if ( this . Milliseconds == other . Milliseconds ) return 0 ;
90- if ( this . Milliseconds < other . Milliseconds ) return - 1 ;
70+ if ( this . ApproximateMilliseconds == other . ApproximateMilliseconds ) return 0 ;
71+ if ( this . ApproximateMilliseconds < other . ApproximateMilliseconds ) return - 1 ;
9172 return 1 ;
9273 }
9374
@@ -115,7 +96,7 @@ public bool Equals(Time other)
11596 {
11697 if ( ReferenceEquals ( null , other ) ) return false ;
11798 if ( ReferenceEquals ( this , other ) ) return true ;
118- return Milliseconds == other . Milliseconds ;
99+ return ( this . ApproximateMilliseconds == other . ApproximateMilliseconds ) ;
119100 }
120101
121102 public override bool Equals ( object obj )
@@ -126,18 +107,57 @@ public override bool Equals(object obj)
126107 return Equals ( ( Time ) obj ) ;
127108 }
128109
129- public override int GetHashCode ( ) => this . Milliseconds . GetHashCode ( ) ;
110+ public override int GetHashCode ( ) => this . ApproximateMilliseconds . GetHashCode ( ) ;
130111
131- private void Reduce ( double ms )
112+ private void SetMilliseconds ( TimeUnit ? interval , double factor )
132113 {
133- this . Milliseconds = ms ;
114+ this . Milliseconds = interval . HasValue ? GetExactMilliseconds ( interval . Value , factor ) : factor ;
115+ this . ApproximateMilliseconds = interval . HasValue ? GetApproximateMilliseconds ( interval . Value , factor ) : factor ;
116+ }
134117
135- if ( ms >= _year )
118+ private double GetExactMilliseconds ( TimeUnit interval , double factor )
119+ {
120+ switch ( interval )
136121 {
137- Factor = ms / _year ;
138- Interval = TimeUnit . Year ;
122+
123+ case TimeUnit . Week :
124+ return factor * _week ;
125+ case TimeUnit . Day :
126+ return factor * _day ;
127+ case TimeUnit . Hour :
128+ return factor * _hour ;
129+ case TimeUnit . Minute :
130+ return factor * _minute ;
131+ case TimeUnit . Second :
132+ return factor * _second ;
133+ case TimeUnit . Year :
134+ case TimeUnit . Month :
135+ // Cannot calculate exact milliseconds for non-fixed intervals
136+ return - 1 ;
137+ default : // ms
138+ return factor ;
139139 }
140- else if ( ms >= _week )
140+ }
141+
142+ private double GetApproximateMilliseconds ( TimeUnit interval , double factor )
143+ {
144+ switch ( interval )
145+ {
146+ case TimeUnit . Year :
147+ return factor * _yearApproximate ;
148+ case TimeUnit . Month :
149+ return factor * _monthApproximate ;
150+ default :
151+ return GetExactMilliseconds ( interval , factor ) ;
152+ }
153+ }
154+
155+ private void Reduce ( double ms )
156+ {
157+ this . Milliseconds = ms ;
158+ this . ApproximateMilliseconds = ms ;
159+
160+ if ( ms >= _week )
141161 {
142162 Factor = ms / _week ;
143163 Interval = TimeUnit . Week ;
@@ -165,10 +185,9 @@ private void Reduce(double ms)
165185 else
166186 {
167187 Factor = ms ;
168- // If milliseconds is < 0 then don't set an interval.
188+ // If milliseconds is <= 0 then don't set an interval.
169189 // This is used when setting things like index.refresh_interval = -1 (the only case where a unit isn't required)
170- if ( ms > 0 )
171- Interval = TimeUnit . Millisecond ;
190+ Interval = ( ms > 0 ) ? ( TimeUnit ? ) TimeUnit . Millisecond : null ;
172191 }
173192 }
174193 }
0 commit comments