Merge pull request #1337 from RyanMelenaNoesis/master
[mono.git] / mcs / class / System.Core / System / TimeZoneInfo.TransitionTime.cs
1 /*
2  * System.TimeZoneInfo.TransitionTime
3  *
4  * Author(s)
5  *      Stephane Delcroix <stephane@delcroix.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  * 
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26
27 #if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
28
29 using System.Runtime.CompilerServices;
30 using System.Runtime.Serialization;
31
32 namespace System
33 {
34 #if NET_4_0 || !INSIDE_CORLIB
35         public
36 #endif
37         sealed partial class TimeZoneInfo
38         {
39                 [SerializableAttribute]
40 #if MOBILE
41         [TypeForwardedFrom (Consts.AssemblySystem_Core)]
42 #elif NET_4_0
43         [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
44 #endif
45                 public struct TransitionTime : IEquatable<TimeZoneInfo.TransitionTime>, ISerializable, IDeserializationCallback
46                 {
47                         DateTime timeOfDay;
48                         public DateTime TimeOfDay {
49                                 get { return timeOfDay; }
50                         }
51
52                         int month;
53                         public int Month {
54                                 get { return month; }
55                         }
56
57                         int day;
58                         public int Day {
59                                 get { 
60 #if STRICT
61                                         if (!isFixedDateRule)
62                                                 throw new Exception ("Day property is not valid for floating date rules");
63 #endif
64                                         return day; 
65                                 }
66                         }
67
68                         int week;
69                         public int Week {
70                                 get { 
71 #if STRICT
72                                         if (isFixedDateRule)
73                                                 throw new Exception ("Week property is not valid for fixed date rules");
74 #endif
75                 
76                                         return week; 
77                                 }
78                         }
79
80                         DayOfWeek dayOfWeek;
81                         public DayOfWeek DayOfWeek {
82                                 get { 
83 #if STRICT
84                                         if (isFixedDateRule)
85                                                 throw new Exception ("DayOfWeek property is not valid for fixed date rules");
86 #endif
87         
88                                         return dayOfWeek; 
89                                 }
90                         }
91
92                         bool isFixedDateRule;
93                         public bool IsFixedDateRule {
94                                 get { return isFixedDateRule; }
95                         }
96
97                         public static TransitionTime CreateFixedDateRule (
98                                 DateTime timeOfDay, 
99                                 int month, 
100                                 int day)
101                         {
102                                 return new TransitionTime (timeOfDay, month, day);
103                         }
104
105                         public static TransitionTime CreateFloatingDateRule (
106                                 DateTime timeOfDay,
107                                 int month,
108                                 int week,
109                                 DayOfWeek dayOfWeek)
110                         {
111                                 return new TransitionTime (timeOfDay, month, week, dayOfWeek);
112                         }
113
114                         private TransitionTime (SerializationInfo info, StreamingContext context)
115                         {
116                                 if (info == null)
117                                         throw new ArgumentNullException ("info");
118                                 timeOfDay = (DateTime) info.GetValue ("TimeOfDay", typeof (DateTime));
119                                 month = (byte) info.GetValue ("Month", typeof (byte));
120                                 week = (byte) info.GetValue ("Week", typeof (byte));
121                                 day = (byte) info.GetValue ("Day", typeof (byte));
122                                 dayOfWeek = (DayOfWeek) info.GetValue ("DayOfWeek", typeof (DayOfWeek));
123                                 isFixedDateRule = (bool) info.GetValue ("IsFixedDateRule", typeof (bool));
124
125                                 if (isFixedDateRule)
126                                 {
127                                         week = -1;
128                                         dayOfWeek = (DayOfWeek) (-1);
129                                 }
130                                 if (!isFixedDateRule)                   
131                                         day = -1;
132                         }
133
134                         private TransitionTime (
135                                 DateTime timeOfDay,
136                                 int month,
137                                 int day) : this (timeOfDay, month)
138                         {
139                                 if (day < 1 || day > 31)
140                                         throw new ArgumentOutOfRangeException ("day parameter is less than 1 or greater than 31");
141
142                                 this.day = day; 
143                                 this.isFixedDateRule = true;
144                         }
145
146                         private TransitionTime (
147                                 DateTime timeOfDay,
148                                 int month,
149                                 int week,
150                                 DayOfWeek dayOfWeek)  : this (timeOfDay, month)
151                         {
152                                 if (week < 1 || week > 5)
153                                         throw new ArgumentOutOfRangeException ("week parameter is less than 1 or greater than 5");
154
155                                 if (dayOfWeek != DayOfWeek.Sunday &&
156                                                 dayOfWeek != DayOfWeek.Monday &&
157                                                 dayOfWeek != DayOfWeek.Tuesday &&
158                                                 dayOfWeek != DayOfWeek.Wednesday &&
159                                                 dayOfWeek != DayOfWeek.Thursday &&
160                                                 dayOfWeek != DayOfWeek.Friday &&
161                                                 dayOfWeek != DayOfWeek.Saturday)
162                                         throw new ArgumentOutOfRangeException ("dayOfWeek parameter is not a member od DayOfWeek enumeration");
163
164                                 this.week = week;
165                                 this.dayOfWeek = dayOfWeek;
166                                 this.isFixedDateRule = false;
167                         }
168
169                         private TransitionTime (
170                                 DateTime timeOfDay,
171                                 int month)
172                         {
173                                 if (timeOfDay.Year != 1 || timeOfDay.Month != 1 || timeOfDay.Day != 1)
174                                         throw new ArgumentException ("timeOfDay parameter has a non-default date component");
175
176                                 if (timeOfDay.Kind != DateTimeKind.Unspecified)
177                                         throw new ArgumentException ("timeOfDay parameter Kind's property is not DateTimeKind.Unspecified");
178
179                                 if (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0)
180                                         throw new ArgumentException ("timeOfDay parameter does not represent a whole number of milliseconds");
181
182                                 if (month < 1 || month > 12)
183                                         throw new ArgumentOutOfRangeException ("month parameter is less than 1 or greater than 12");
184                                 
185                                 this.timeOfDay = timeOfDay;
186                                 this.month = month;
187
188                                 this.week = -1;
189                                 this.dayOfWeek = (System.DayOfWeek)(-1);
190                                 this.day = -1;
191                                 this.isFixedDateRule = false;
192                         }
193
194                         public static bool operator == (TransitionTime t1, TransitionTime t2)
195                         {
196                                 return ( t1.day == t2.day &&
197                                                 t1.dayOfWeek == t2.dayOfWeek &&
198                                                 t1.isFixedDateRule == t2.isFixedDateRule &&
199                                                 t1.month == t2.month &&
200                                                 t1.timeOfDay == t2.timeOfDay &&
201                                                 t1.week == t2.week);    
202                         }
203
204                         public static bool operator != (TransitionTime t1, TransitionTime t2)
205                         {
206                                 return !(t1 == t2);
207                         }
208
209
210 #if NET_4_0
211                         void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
212 #else
213                         public void GetObjectData (SerializationInfo info, StreamingContext context)
214 #endif
215                         {
216                                 if (info == null)
217                                         throw new ArgumentNullException ("info");
218                                 info.AddValue ("TimeOfDay", TimeOfDay);
219                                 info.AddValue ("Month", System.Convert.ToByte(Month));
220                                 if (week > -1)
221                                         info.AddValue ("Week", System.Convert.ToByte(week));
222                                 else 
223                                         info.AddValue ("Week", (byte) 1);
224                                 if (day > -1)
225                                         info.AddValue ("Day", System.Convert.ToByte(day));
226                                 else
227                                         info.AddValue ("Day", (byte) 1);
228                                 if (dayOfWeek !=  ((System.DayOfWeek) (-1)))
229                                         info.AddValue ("DayOfWeek", dayOfWeek);
230                                 else
231                                         info.AddValue ("DayOfWeek", DayOfWeek.Sunday);
232                                 info.AddValue ("IsFixedDateRule", IsFixedDateRule);
233                         }       
234         
235                         public override bool Equals (object obj)
236                         {
237                                 if (obj is TransitionTime)
238                                         return this == (TransitionTime) obj;
239                                 return false;
240                         }
241
242                         public bool Equals (TimeZoneInfo.TransitionTime other)
243                         {
244                                 return this == other;
245                         }
246
247                         public override int GetHashCode ()
248                         {
249                                 return (day ^ (int)dayOfWeek ^ month ^ (int)timeOfDay.Ticks ^ week);
250                         }
251
252 #if NET_4_0
253                         void IDeserializationCallback.OnDeserialization (object sender)
254 #else
255                         public void OnDeserialization (object sender)
256 #endif
257                         {
258                                 try {
259                                         TimeZoneInfo.TransitionTime.Validate (timeOfDay, month, week, day, dayOfWeek, isFixedDateRule);
260                                 } catch (ArgumentException ex) {
261                                         throw new SerializationException ("invalid serialization data", ex);
262                                 }
263                         }
264
265                         private static void Validate (DateTime timeOfDay, int month,int week, int day, DayOfWeek dayOfWeek, bool isFixedDateRule)
266                         {
267                                 if (timeOfDay.Year != 1 || timeOfDay.Month != 1 || timeOfDay.Day != 1)
268                                         throw new ArgumentException ("timeOfDay parameter has a non-default date component");
269
270                                 if (timeOfDay.Kind != DateTimeKind.Unspecified)
271                                         throw new ArgumentException ("timeOfDay parameter Kind's property is not DateTimeKind.Unspecified");
272
273                                 if (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0)
274                                         throw new ArgumentException ("timeOfDay parameter does not represent a whole number of milliseconds");
275
276                                 if (day < 1 || day > 31) {
277                                         if (!(!isFixedDateRule && day == -1))
278                                                 throw new ArgumentOutOfRangeException ("day parameter is less than 1 or greater than 31");
279                                 }
280
281                                 if (week < 1 || week > 5) {
282                                         if (!(isFixedDateRule && week == -1))
283                                                 throw new ArgumentOutOfRangeException ("week parameter is less than 1 or greater than 5");
284                                 }
285
286                                 if (month < 1 || month > 12)
287                                         throw new ArgumentOutOfRangeException ("month parameter is less than 1 or greater than 12");
288
289                                 if (dayOfWeek != DayOfWeek.Sunday &&
290                                                 dayOfWeek != DayOfWeek.Monday &&
291                                                 dayOfWeek != DayOfWeek.Tuesday &&
292                                                 dayOfWeek != DayOfWeek.Wednesday &&
293                                                 dayOfWeek != DayOfWeek.Thursday &&
294                                                 dayOfWeek != DayOfWeek.Friday &&
295                                                 dayOfWeek != DayOfWeek.Saturday) {
296                                         if (!(isFixedDateRule && dayOfWeek == (DayOfWeek) (-1)))
297                                                 throw new ArgumentOutOfRangeException ("dayOfWeek parameter is not a member od DayOfWeek enumeration");
298                                 }
299                         }
300                 }
301         }
302 }
303
304 #endif