1 module skia.TimeSpan;
2 /// https://dlang.org/phobos/std_datetime.html
3 import std.format;
4 
5 struct TimeSpan
6 {
7     const long TicksPerDay = 864000000000L;
8 
9 	const long TicksPerHour = 36000000000L;
10 
11 	const long TicksPerMinute = 600000000L;
12 
13 	const long TicksPerSecond = 10000000L;
14 
15     const long TicksPerMillisecond = 10000L;
16 
17     private long _ticks;
18     long Ticks() { return _ticks; }
19 
20     private int _days;
21     int Days() { return _days; }
22 
23     private int _hours;
24     int Hours() { return _hours; }
25 
26     private int _minutes;
27     int Minutes() { return _minutes; }
28 
29     private int _seconds;
30     int Seconds() { return _seconds; }
31 
32     private int _milliseconds;
33     int Milliseconds() { return _milliseconds; }
34 
35     private double _totalDays;
36     double TotalDays() { return _totalDays; }
37 
38     private double _totalHours;
39     double TotalHours() { return _totalHours; }
40 
41     private double _totalMinutes;
42     double TotalMinutes() { return _totalMinutes; }
43 
44     private double _totalSeconds;
45     double TotalSeconds() { return _totalSeconds; }
46 
47     private double _totalMilliseconds;
48     double TotalMilliseconds() { return _totalMilliseconds; }
49 
50     this(int hours, int minutes, int seconds) 
51     {
52         this._ticks = cast(long)hours*TicksPerHour + 
53                       cast(long)minutes*TicksPerMinute + 
54                       cast(long)seconds*TicksPerSecond;
55 
56         this.initProperty();
57     }
58 
59     this(int days, int hours, int minutes, int seconds) 
60     {
61         this._ticks = cast(long)days*TicksPerDay + 
62                       cast(long)hours*TicksPerHour + 
63                       cast(long)minutes*TicksPerMinute + 
64                       cast(long)seconds*TicksPerSecond;
65 
66         this.initProperty();
67     }
68 
69     this(int days, int hours, int minutes, int seconds, int milliseconds)
70     {
71         this._ticks = cast(long)days*TicksPerDay + 
72                       cast(long)hours*TicksPerHour + 
73                       cast(long)minutes*TicksPerMinute + 
74                       cast(long)seconds*TicksPerSecond + 
75                       cast(long)milliseconds*TicksPerMillisecond;
76 
77         this.initProperty();
78     }
79 
80 	this(long ticks)
81     {
82         this._ticks = ticks;
83         this.initProperty();
84     }
85 
86     private void initProperty() 
87     {
88         double t = cast(double)_ticks;
89         // total
90         this._totalDays = t/cast(double)TicksPerDay;
91         this._totalHours = t/cast(double)TicksPerHour;
92         this._totalMinutes = t/cast(double)TicksPerMinute;
93         this._totalSeconds = t/cast(double)TicksPerSecond;
94         this._totalMilliseconds = t/cast(double)TicksPerMillisecond;
95         // single
96         this._days = cast(int)_totalDays;
97         this._hours = cast(int)_totalHours % 24;
98         this._minutes = cast(int)_totalMinutes % 60;
99         this._seconds = cast(int)_totalSeconds % 60;
100         this._milliseconds = cast(int)(_totalMilliseconds - cast(long)_seconds*TicksPerMillisecond);
101     }
102 
103     static TimeSpan Zero() 
104     {
105         TimeSpan s;
106         return s;
107     }
108 
109 	TimeSpan Add(TimeSpan ts)
110     {
111         TimeSpan s;
112         s._ticks = this._ticks + ts._ticks;
113         s.initProperty();
114         return s;
115     }
116     
117     static int Compare(TimeSpan t1, TimeSpan t2)
118     {
119         auto space = t1._ticks - t2._ticks;
120         if (space > 0) {
121             return 1;
122         }
123         if (space == 0) {
124             return 0;
125         }
126         return -1;
127     }
128 
129     int CompareTo(TimeSpan ts)
130     {
131         auto space = this._ticks - ts._ticks;
132         if (space > 0) {
133             return 1;
134         }
135         if (space == 0) {
136             return 0;
137         }
138         return -1;
139     }
140 
141     // 获取TimeSpan的绝对值
142     TimeSpan Duration()
143     {
144         TimeSpan s = this;
145         if (s._ticks < 0) {
146             s._ticks = -s._ticks;
147         }
148         s.initProperty();
149         return s;
150     }
151     /// 获取TimeSpan的相反数
152     TimeSpan Negate()
153     {
154         TimeSpan s = this;
155         s._ticks = -s._ticks;
156         s.initProperty();
157         return s;
158     }
159 
160     /// Equal
161     bool Equals(TimeSpan ts)
162     {
163         return this._ticks == ts._ticks;
164     }
165 
166     static bool Equals(TimeSpan t1, TimeSpan t2)
167     {
168         return t1._ticks == t2._ticks;
169     }
170 
171 
172     /// From
173 	static TimeSpan FromDays(double value)
174     {
175         TimeSpan s;
176         auto t = cast(double)s.TicksPerDay;
177         s._ticks = cast(long)(t*value); 
178         s.initProperty();
179         return s;
180     }
181 
182 	static TimeSpan FromHours(double value)
183     {
184         TimeSpan s;
185         auto t = cast(double)s.TicksPerHour;
186         s._ticks = cast(long)(t*value);
187         s.initProperty();
188         return s;
189     }
190 
191 	static TimeSpan FromMinutes(double value)
192     {
193         TimeSpan s;
194         auto t = cast(double)s.TicksPerMinute;
195         s._ticks = cast(long)(t*value);
196         s.initProperty();
197         return s;
198     }
199 
200 	static TimeSpan FromSeconds(double value)
201     {
202         TimeSpan s;
203         auto t = cast(double)s.TicksPerSecond;
204         s._ticks = cast(long)(t*value);
205         s.initProperty();
206         return s;
207     }
208 
209     static TimeSpan FromMilliseconds(double value)
210     {
211         TimeSpan s;
212         auto t = cast(double)s.TicksPerMillisecond;
213         s._ticks = cast(long)(t*value);
214         s.initProperty();
215         return s;
216     }
217 
218 	static TimeSpan From_ticks(long value)
219     {
220         TimeSpan s;
221         s._ticks = value;
222         s.initProperty();
223         return s;
224     }
225 
226     TimeSpan opBinary(string op)(TimeSpan ts) if(op == "+" || op == "-")
227     {
228         TimeSpan s;
229         if (op == "+")  {
230             s._ticks = this._ticks + ts._ticks;
231         } else {
232             s._ticks = this._ticks - ts._ticks;
233         }
234         s.initProperty();
235         return s;
236     }
237 
238     static TimeSpan opBinary(string op)(TimeSpan t1, TimeSpan t2) if(op == "+" || op == "-")
239     {
240         TimeSpan s;
241         if (op == "+")  {
242             s._ticks = t1._ticks + t2._ticks;
243         } else {
244             s._ticks = t1._ticks - t2._ticks;
245         }
246         s.initProperty();
247         return s;
248     }
249 
250     /**
251         /// operate "==" | "!=" => opCmp
252         static bool opBinary(string op)(TimeSpan t1, TimeSpan t2) if(op == "==" || op == "!=")
253         {
254             switch (op)
255             {
256                 case "==":
257                     return t1._ticks == t2._ticks;
258                     break;
259                 case "!=":
260                     return t1._ticks != t2._ticks;
261                     break;
262                 default:
263                     return true;
264                     break;
265             }
266         }
267      */
268 
269     long opCmp(const ref TimeSpan ts) const
270     {
271       return (_ticks == ts._ticks ? (ts._ticks - _ticks) : _ticks - ts._ticks);
272     }
273 
274     /// 1.02:03:10.0200000
275     string ToString()
276     {
277         auto ms = cast(long)Milliseconds;
278         ms = ms * TicksPerMillisecond;
279         string l = format("%07d", ms);
280 
281         string d = format("%d", _days);
282         string h = format("%02d", _hours);
283         string m = format("%02d", _minutes);
284         string s = format("%02d", _seconds);
285         return d ~"."~ h ~":"~ m ~":"~ s ~"."~ l;
286     }
287 
288     /// 字符串转TimeSpan
289     // static bool TryParse (string input, IFormatProvider formatProvider, out TimeSpan result)
290     static bool TryParse (string input, string formatProvider, inout TimeSpan result)
291     {
292         return true;
293     }
294 }