2001-07-19 Duco Fijma (duco@lorentz.xs4all.nl)
[mono.git] / mcs / class / corlib / System / TimeSpan.cs
1 //
2 // System.TimeSpan.cs
3 //
4 // author:
5 //   Duco Fijma (duco@lorentz.xs4all.nl)
6 //
7 //   (C) 2001 Duco Fijma
8
9 namespace System {
10         
11         public struct TimeSpan :  IComparable  {
12                 private long ticks;
13
14                 // Ctors
15
16                 public TimeSpan (long value) { ticks = value; }
17                 public TimeSpan (int hours, int minutes, int seconds) 
18                         : this(0, hours, minutes, seconds, 0) {}
19                 public TimeSpan (int days, int hours, int minutes, int seconds) 
20                         : this(days, hours, minutes, seconds, 0) {}
21                 public TimeSpan (int days, int hours, int minutes, int seconds, int milliseconds)
22                 {
23                         ticks = TicksPerDay * days + 
24                                 TicksPerHour * hours +
25                                 TicksPerMinute * minutes +
26                                 TicksPerSecond * seconds +
27                                 TicksPerMillisecond * milliseconds;
28                 }
29                 
30                 // Fields
31
32                 public static readonly TimeSpan MaxValue = new TimeSpan (long.MaxValue);
33                 public static readonly TimeSpan MinValue = new TimeSpan (long.MinValue);
34                 public const long TicksPerDay = 864000000000L;
35                 public const long TicksPerHour = 36000000000L;
36                 public const long TicksPerMillisecond = 10000L;
37                 public const long TicksPerMinute = 600000000L;
38                 public const long TicksPerSecond = 10000000L;
39                 public static readonly TimeSpan Zero = new TimeSpan (0L);
40
41                 // Properties
42
43                 public int Days
44                 {
45                         get {
46                                 return (int) TotalDays;
47                         }
48                 }
49
50                 public int Hours
51                 {
52                         get {
53                                 return (int) (ticks % TicksPerDay / TicksPerHour);
54                         }
55                 }
56
57                 public int Milliseconds
58                 {
59                         get
60                         {
61                                 return (int) (ticks % TicksPerSecond / TicksPerMillisecond);
62                         }
63                 }
64
65                 public int Minutes
66                 {
67                         get
68                         {
69                                 return (int) (ticks % TicksPerHour / TicksPerMinute);
70                         }
71                 }
72
73                 public int Seconds
74                 {
75                         get
76                         {
77                                 return (int) (ticks % TicksPerMinute / TicksPerSecond);
78                         }
79                 }
80
81                 public long Ticks
82                 { 
83                         get
84                         {
85                                 return ticks;
86                         }
87                 }
88
89                 public double TotalDays
90                 {
91                         get
92                         {
93                                 return (double) ticks / TicksPerDay;
94                         }
95                 }
96
97                 public double TotalHours
98                 {
99                         get
100                         {
101                                 return (double) ticks / TicksPerHour;
102                         }
103                 }
104
105                 public double TotalMilliseconds
106                 {
107                         get
108                         {
109                                 return (double) ticks  / TicksPerMillisecond;
110                         }
111                 }
112
113                 public double TotalMinutes
114                 {
115                         get {
116                                 return (double) ticks / TicksPerMinute;
117                         }
118                 }
119
120                 public double TotalSeconds
121                 {
122                         get {
123                                 return (double) ticks / TicksPerSecond;
124                         }
125                 }
126
127                 // Methods
128
129                 public TimeSpan Add (TimeSpan ts)
130                 {
131                         checked {
132                                 return new TimeSpan (ticks+ts.Ticks);
133                         }
134                 }
135
136                 public static int Compare (TimeSpan t1, TimeSpan t2)
137                 {
138                         if (t1.ticks < t2.ticks) {
139                                 return -1;
140                         }
141                         else if (t1.ticks > t2.ticks) {
142                                 return 1;
143                         }
144                         else {
145                                 return 0;
146                         }
147                 }
148
149                 public int CompareTo (object value)
150                 {
151                         
152                         if (value == null ) {
153                                 return 1;
154                         }
155
156                         if (!(value is TimeSpan)) {
157                                 throw new ArgumentException("Argument of System.TimeSpan.CompareTo should be a TimeSpan");
158                         }
159                 
160                         return Compare(this, (TimeSpan) value);
161                 }
162
163                 // Overflow issue for Duration is like for Negate.
164                 public TimeSpan Duration ()
165                 {
166                         checked {
167                                 return new TimeSpan (Math.Abs (ticks));
168                         }
169                 }
170
171                 // TODO: Consider implementing this version
172                 // in terms of Equals(TimeSPan, TimeSpan)
173                 public override bool Equals (object value)
174                 {
175                         if (value == null || !(value is TimeSpan)) {
176                                 return false;
177                         }
178                         return ticks == ((TimeSpan) (value)).ticks;
179                 }
180
181                 public static new bool Equals(TimeSpan t1, TimeSpan t2)
182                 {
183                         return t1.Equals (t2);
184                 }
185
186                 // Implementing FromDays -> FromHours -> FromMinutes -> FromSeconds ->
187                 // FromMilliseconds as done here is probably not the most efficient
188                 // way. 
189
190                 public static TimeSpan FromDays (double value)
191                 {
192                         if (Double.IsNaN(value) || Double.IsNegativeInfinity(value)) {
193                                 return MinValue;
194                         }
195
196                         if (Double.IsPositiveInfinity(value)) {
197                                 return MaxValue;
198                         }
199
200                         return new TimeSpan((int) value,0,0,0,0) + FromHours ((value - ((int) value)) * 24);
201                 }
202
203                 public static TimeSpan FromHours (double value)
204                 {
205                         if (Double.IsNaN(value) || Double.IsNegativeInfinity(value)) {
206                                 return MinValue;
207                         }
208
209                         if (Double.IsPositiveInfinity(value)) {
210                                 return MaxValue;
211                         }
212
213                         return new TimeSpan ((int) value,0,0) + FromMinutes ((value - ((int) value)) * 60);
214                 }
215
216                 public static TimeSpan FromMinutes(double value)
217                 {
218                         if (Double.IsNaN(value) || Double.IsNegativeInfinity(value)) {
219                                 return MinValue;
220                         }
221
222                         if (Double.IsPositiveInfinity(value)) {
223                                 return MaxValue;
224                         }
225
226                         return new TimeSpan (0,(int) value,0) + FromSeconds((value - ((int) value)) * 60);
227                 }
228
229                 public static TimeSpan FromSeconds(double value)
230                 {
231                         if (Double.IsNaN(value) || Double.IsNegativeInfinity(value)) {
232                                 return MinValue;
233                         }
234
235                         if (Double.IsPositiveInfinity(value)) {
236                                 return MaxValue;
237                         }
238
239                         return new TimeSpan (0,0,0,(int) value,((int) ((value - ((int) value)) * 1000)));
240
241                 }
242
243                 public static TimeSpan FromTicks (long value)
244                 {
245                         return new TimeSpan (value);
246                 }
247
248                 public override int GetHashCode()
249                 {
250                         return ticks.GetHashCode();
251                 }
252
253                 // TODO: It makes sense that Negate can throw an overflow
254                 // exception (if negating MinValue). Is this specified
255                 // somewhere?
256                 public TimeSpan Negate()
257                 {
258                         checked {
259                                 return new TimeSpan(- ticks);
260                         }
261                 }
262
263                 // TODO: implement
264                 public static TimeSpan Parse(string s) 
265                 {
266                         return Zero;
267                 }
268
269                 public TimeSpan Subtract(TimeSpan ts)
270                 {
271                         checked {
272                                 return new TimeSpan(ticks - ts.Ticks);
273                         }
274                 }
275
276                 public override string ToString()
277                 {
278                         string res = "";        
279
280                         if (ticks < 0) {
281                                 res += "-";
282                         }
283
284                         // We need to take absolute values of all components.
285                         // Can't handle negative timespans by negating the TimeSpan
286                         // as a whole. This would lead to an overflow for the 
287                         // degenerate case "TimeSpan.MinValue.ToString()".
288
289                         if (Days != 0) {
290                                 res += Math.Abs(Days) + "." ;
291                         }
292
293                         res += string.Format("{0:00}:{1:00}:{2:00}", Math.Abs(Hours), Math.Abs(Minutes), Math.Abs(Seconds));
294
295                         int fractional = (int) Math.Abs(ticks % TicksPerSecond);
296                         if (fractional != 0) {
297                                 res += string.Format(".{0:0000000}", fractional);
298                         }
299  
300                         return res;
301                 }
302
303                 public static TimeSpan operator +(TimeSpan t1, TimeSpan t2)
304                 {
305                         return t1.Add(t2);
306                 }
307
308                 public static bool operator ==(TimeSpan t1, TimeSpan t2)
309                 {
310                         return Compare(t1, t2) == 0;
311                 }
312
313                 public static bool operator >(TimeSpan t1, TimeSpan t2)
314                 {
315                         return Compare(t1, t2) == 1;
316                 }
317
318                 public static bool operator >=(TimeSpan t1, TimeSpan t2)
319                 {
320                         return Compare(t1, t2) != -1;
321                 }
322
323                 public static bool operator !=(TimeSpan t1, TimeSpan t2)
324                 {
325                         return Compare(t1, t2) != 0;
326                 }
327
328                 public static bool operator <(TimeSpan t1, TimeSpan t2)
329                 {
330                         return Compare(t1, t2) == -1;
331                 }
332
333                 public static bool operator <=(TimeSpan t1, TimeSpan t2)
334                 {
335                         return Compare(t1, t2) != 1;
336                 }
337
338                 public static TimeSpan operator -(TimeSpan t1, TimeSpan t2)
339                 {
340                         return t1.Subtract(t2);
341                 }
342
343                 public static TimeSpan operator -(TimeSpan t)
344                 {
345                         return t.Negate();
346                 }
347
348                 public static TimeSpan operator +(TimeSpan t)
349                 {
350                         return t;
351                 }
352         }
353 }
354