Merge pull request #1319 from directhex/systemwide-per-arch-aot-cache
[mono.git] / mcs / class / System.Core / System / TimeZoneInfo.AdjustmentRule.cs
1 /*
2  * System.TimeZoneInfo.AdjustmentRule
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 using System.Runtime.CompilerServices;
29 using System.Runtime.Serialization;
30
31 namespace System
32 {
33 #if NET_4_0 || !INSIDE_CORLIB
34         public
35 #endif
36         sealed partial class TimeZoneInfo {
37                 [SerializableAttribute]
38 #if MOBILE
39         [TypeForwardedFrom (Consts.AssemblySystem_Core)]
40 #elif NET_4_0
41         [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
42 #endif
43                 public sealed class AdjustmentRule : IEquatable<TimeZoneInfo.AdjustmentRule>, ISerializable, IDeserializationCallback
44                 {
45                         DateTime dateEnd;
46                         public DateTime DateEnd {
47                                 get { return dateEnd; } 
48                         }
49
50                         DateTime dateStart;
51                         public DateTime DateStart {
52                                 get { return dateStart; }
53                         }
54
55                         TimeSpan daylightDelta;
56                         public TimeSpan DaylightDelta {
57                                 get { return daylightDelta; }
58                         }
59
60                         TransitionTime daylightTransitionEnd;
61                         public TransitionTime DaylightTransitionEnd {
62                                 get { return daylightTransitionEnd; }
63                         }
64
65                         TransitionTime daylightTransitionStart;
66                         public TransitionTime DaylightTransitionStart {
67                                 get { return daylightTransitionStart; }
68                         }
69
70                         public static AdjustmentRule CreateAdjustmentRule (
71                                 DateTime dateStart,
72                                 DateTime dateEnd,
73                                 TimeSpan daylightDelta,
74                                 TransitionTime daylightTransitionStart,
75                                 TransitionTime daylightTransitionEnd)
76                         {
77                                 return new AdjustmentRule (dateStart, dateEnd, daylightDelta, daylightTransitionStart, daylightTransitionEnd);
78                         }
79
80                         private AdjustmentRule (SerializationInfo info, StreamingContext context)
81                         {
82                                 if (info == null)
83                                         throw new ArgumentNullException ("info");
84                                 dateStart = (DateTime) info.GetValue ("DateStart", typeof (DateTime));
85                                 dateEnd = (DateTime) info.GetValue ("DateEnd", typeof (DateTime));
86                                 daylightDelta = (TimeSpan) info.GetValue ("DaylightDelta", typeof (TimeSpan));
87                                 daylightTransitionStart = (TimeZoneInfo.TransitionTime) info.GetValue ("DaylightTransitionStart", typeof (TimeZoneInfo.TransitionTime));
88                                 daylightTransitionEnd = (TimeZoneInfo.TransitionTime) info.GetValue ("DaylightTransitionEnd", typeof (TimeZoneInfo.TransitionTime));
89                         }
90                         
91                         private AdjustmentRule (
92                                 DateTime dateStart,
93                                 DateTime dateEnd,
94                                 TimeSpan daylightDelta,
95                                 TransitionTime daylightTransitionStart,
96                                 TransitionTime daylightTransitionEnd)
97                         {
98                                 if (dateStart.Kind != DateTimeKind.Unspecified || dateEnd.Kind != DateTimeKind.Unspecified)
99                                         throw new ArgumentException ("the Kind property of dateStart or dateEnd parameter does not equal DateTimeKind.Unspecified");
100
101                                 if (daylightTransitionStart == daylightTransitionEnd)
102                                         throw new ArgumentException ("daylightTransitionStart parameter cannot equal daylightTransitionEnd parameter");
103
104                                 if (dateStart.Ticks % TimeSpan.TicksPerDay != 0 || dateEnd.Ticks % TimeSpan.TicksPerDay != 0)
105                                         throw new ArgumentException ("dateStart or dateEnd parameter includes a time of day value");
106
107                                 if (dateEnd < dateStart)
108                                         throw new ArgumentOutOfRangeException ("dateEnd is earlier than dateStart");
109
110                                 if (daylightDelta > new TimeSpan (14, 0, 0) || daylightDelta < new TimeSpan (-14, 0, 0))
111                                         throw new ArgumentOutOfRangeException ("daylightDelta is less than -14 or greater than 14 hours");
112
113                                 if (daylightDelta.Ticks % TimeSpan.TicksPerSecond != 0)
114                                         throw new ArgumentOutOfRangeException ("daylightDelta parameter does not represent a whole number of seconds");
115
116                                 this.dateStart = dateStart;
117                                 this.dateEnd = dateEnd;
118                                 this.daylightDelta = daylightDelta;
119                                 this.daylightTransitionStart = daylightTransitionStart;
120                                 this.daylightTransitionEnd = daylightTransitionEnd;
121                         }
122
123                         public bool Equals (TimeZoneInfo.AdjustmentRule other)
124                         {
125                                 return dateStart == other.dateStart &&
126                                         dateEnd == other.dateEnd &&
127                                         daylightDelta == other.daylightDelta && 
128                                         daylightTransitionStart == other.daylightTransitionStart &&
129                                         daylightTransitionEnd == other.daylightTransitionEnd;
130                         }
131
132                         public override int GetHashCode ()
133                         {
134                                 return dateStart.GetHashCode () ^ 
135                                         dateEnd.GetHashCode () ^
136                                         daylightDelta.GetHashCode () ^
137                                         daylightTransitionStart.GetHashCode () ^
138                                         daylightTransitionEnd.GetHashCode ();
139                         }
140                                         
141 #if NET_4_0
142                         void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
143 #else
144                         public void GetObjectData (SerializationInfo info, StreamingContext context)
145 #endif
146                         {
147                                 if (info == null)
148                                         throw new ArgumentNullException ("info");
149                                 info.AddValue ("DateStart", DateStart);
150                                 info.AddValue ("DateEnd", DateEnd);
151                                 info.AddValue ("DaylightDelta", DaylightDelta);
152                                 info.AddValue ("DaylightTransitionStart", DaylightTransitionStart);
153                                 info.AddValue ("DaylightTransitionEnd", DaylightTransitionEnd);
154                         }
155 #if NET_4_0
156                         void IDeserializationCallback.OnDeserialization (object sender)
157 #else
158                         public void OnDeserialization (object sender)
159 #endif
160                         {
161                                 try {
162                                         TimeZoneInfo.AdjustmentRule.Validate (dateStart, dateEnd, daylightDelta, 
163                                                                               daylightTransitionStart, daylightTransitionEnd);
164                                 } catch (ArgumentException ex) {
165                                         throw new SerializationException ("invalid serialization data", ex);
166                                 }
167                         }
168
169                         private static void Validate (
170                                 DateTime dateStart,
171                                 DateTime dateEnd,
172                                 TimeSpan daylightDelta,
173                                 TransitionTime daylightTransitionStart,
174                                 TransitionTime daylightTransitionEnd)
175                         {
176                                 if (dateStart.Kind != DateTimeKind.Unspecified || dateEnd.Kind != DateTimeKind.Unspecified)
177                                         throw new ArgumentException ("the Kind property of dateStart or dateEnd parameter does not equal DateTimeKind.Unspecified");
178
179                                 if (daylightTransitionStart == daylightTransitionEnd)
180                                         throw new ArgumentException ("daylightTransitionStart parameter cannot equal daylightTransitionEnd parameter");
181
182                                 if (dateStart.Ticks % TimeSpan.TicksPerDay != 0 || dateEnd.Ticks % TimeSpan.TicksPerDay != 0)
183                                         throw new ArgumentException ("dateStart or dateEnd parameter includes a time of day value");
184
185                                 if (dateEnd < dateStart)
186                                         throw new ArgumentOutOfRangeException ("dateEnd is earlier than dateStart");
187
188                                 if (daylightDelta > new TimeSpan (14, 0, 0) || daylightDelta < new TimeSpan (-14, 0, 0))
189                                         throw new ArgumentOutOfRangeException ("daylightDelta is less than -14 or greater than 14 hours");
190
191                                 if (daylightDelta.Ticks % TimeSpan.TicksPerSecond != 0)
192                                         throw new ArgumentOutOfRangeException ("daylightDelta parameter does not represent a whole number of seconds");
193                         }
194                 }
195         }
196 }
197
198 #endif