Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / DateTimeStorage.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DateTimeStorage.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 // <owner current="false" primary="false">[....]</owner>
8 //------------------------------------------------------------------------------
9
10 namespace System.Data.Common {
11     using System;
12     using System.Xml;
13     using System.Data.SqlTypes;
14     using System.Collections;
15
16     internal sealed class DateTimeStorage : DataStorage {
17
18         private static readonly DateTime defaultValue = DateTime.MinValue;
19
20         private DateTime[] values;
21
22         internal DateTimeStorage(DataColumn column)
23         : base(column, typeof(DateTime), defaultValue, StorageType.DateTime) {
24         }
25
26         override public Object Aggregate(int[] records, AggregateType kind) {
27             bool hasData = false;
28             try {
29                 switch (kind) {
30                     case AggregateType.Min:
31                         DateTime min = DateTime.MaxValue;
32                         for (int i = 0; i < records.Length; i++) {
33                             int record = records[i];
34                             if (HasValue(record)) {
35                                 min=(DateTime.Compare(values[record],min) < 0) ? values[record] : min;
36                                 hasData = true;
37                             }
38                         }
39                         if (hasData) {
40                             return min;
41                         }
42                         return NullValue;
43
44                     case AggregateType.Max:
45                         DateTime max = DateTime.MinValue;
46                         for (int i = 0; i < records.Length; i++) {
47                             int record = records[i];
48                             if (HasValue(record)) {
49                                 max=(DateTime.Compare(values[record],max) >= 0) ? values[record] : max;
50                                 hasData = true;
51                             }
52                         }
53                         if (hasData) {
54                             return max;
55                         }
56                         return NullValue;
57
58                     case AggregateType.First:
59                         if (records.Length > 0) {
60                             return values[records[0]];
61                         }
62                         return null;
63
64                     case AggregateType.Count:
65                         int count = 0;
66                         for (int i = 0; i < records.Length; i++) {
67                             if (HasValue(records[i])) {
68                                 count++;
69                             }
70                         }
71                         return count;
72                 }
73             }
74             catch (OverflowException) {
75                 throw ExprException.Overflow(typeof(DateTime));
76             }
77             throw ExceptionBuilder.AggregateException(kind, DataType);
78         }
79
80         override public int Compare(int recordNo1, int recordNo2) {
81             DateTime valueNo1 = values[recordNo1];
82             DateTime valueNo2 = values[recordNo2];
83             
84             if (valueNo1 == defaultValue || valueNo2 == defaultValue) {
85                 int bitCheck = CompareBits(recordNo1, recordNo2);
86                 if (0 != bitCheck) {
87                     return bitCheck;
88                 }
89             }
90             return DateTime.Compare(valueNo1, valueNo2);
91         }
92
93         public override int CompareValueTo(int recordNo, object value) {
94             System.Diagnostics.Debug.Assert(0 <= recordNo, "Invalid record");
95             System.Diagnostics.Debug.Assert(null != value, "null value");
96
97             if (NullValue == value) {
98                 return (HasValue(recordNo) ? 1 : 0);
99             }
100
101             DateTime valueNo1 = values[recordNo];
102             if ((defaultValue == valueNo1) && !HasValue(recordNo)) {
103                 return -1;
104             }
105             return DateTime.Compare(valueNo1, (DateTime)value);
106         }
107
108         public override object ConvertValue(object value) {
109             if (NullValue != value) {
110                 if (null != value) {
111                     value = ((IConvertible)value).ToDateTime(FormatProvider);
112                 }
113                 else {
114                     value = NullValue;
115                 }
116             }
117             return value;
118         }
119
120         override public void Copy(int recordNo1, int recordNo2) {
121             CopyBits(recordNo1, recordNo2);
122             values[recordNo2] = values[recordNo1];
123         }
124
125         override public Object Get(int record) {
126             // SQLBU 408233: two equal DateTime with different .Kind are equal
127             DateTime value = values[record];
128             if ((value != defaultValue) || HasValue(record)) {
129                 return value;
130             }
131             return NullValue;
132         }
133
134         override public void Set(int record, Object value) {
135             System.Diagnostics.Debug.Assert(null != value, "null value");
136             if (NullValue == value) {
137                 values[record] = defaultValue;
138                 SetNullBit(record, true);
139             }
140             else {
141                 DateTime retVal;
142                 DateTime tmpValue = ((IConvertible)value).ToDateTime(FormatProvider);
143                 switch (DateTimeMode) {
144                     case DataSetDateTime.Utc:
145                         if (tmpValue.Kind == DateTimeKind.Utc) {
146                             retVal = tmpValue;
147                         }
148                         else if (tmpValue.Kind == DateTimeKind.Local) {
149                             retVal = tmpValue.ToUniversalTime();
150                         }
151                         else {
152                             retVal = DateTime.SpecifyKind(tmpValue, DateTimeKind.Utc);
153                         }
154                         break;
155                     case DataSetDateTime.Local:
156                         if (tmpValue.Kind == DateTimeKind.Local) {
157                             retVal = tmpValue;
158                         }
159                         else if (tmpValue.Kind == DateTimeKind.Utc) {
160                             retVal = tmpValue.ToLocalTime();
161                         }
162                         else {
163                             retVal =  DateTime.SpecifyKind(tmpValue, DateTimeKind.Local);
164                         }
165                         break;
166                     case DataSetDateTime.Unspecified:
167                     case DataSetDateTime.UnspecifiedLocal:
168                         retVal = DateTime.SpecifyKind(tmpValue, DateTimeKind.Unspecified); 
169                         break;
170                     default:
171                         throw ExceptionBuilder.InvalidDateTimeMode(DateTimeMode);
172                 }
173                 values[record] = retVal;
174                 SetNullBit(record, false);
175             }
176         }
177
178         override public void SetCapacity(int capacity) {
179             DateTime[] newValues = new DateTime[capacity];
180             if (null != values) {
181                 Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length));
182             }
183             values = newValues;
184             base.SetCapacity(capacity);
185         }
186
187         override public object ConvertXmlToObject(string s) {
188             object retValue;
189             if (DateTimeMode == DataSetDateTime.UnspecifiedLocal) {
190                 retValue = XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.Unspecified);
191             }
192             else {
193                 retValue = XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind);
194             }
195             return retValue;
196         }
197
198         override public string ConvertObjectToXml(object value) {
199             string retValue;
200             if (DateTimeMode == DataSetDateTime.UnspecifiedLocal) {
201                 retValue = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Local);
202             }
203             else {
204                 retValue = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
205             }
206             return retValue;
207         }
208
209         override protected object GetEmptyStorage(int recordCount) {
210             return new DateTime[recordCount];
211         }
212
213         override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) {
214             DateTime[] typedStore = (DateTime[]) store;
215             bool isnull = !HasValue(record);
216             if (isnull || ( 0 == (DateTimeMode & DataSetDateTime.Local))) {
217                 typedStore[storeIndex] = values[record]; // already universal time
218             }
219             else {
220                 typedStore[storeIndex] = values[record].ToUniversalTime();
221             }
222             nullbits.Set(storeIndex, isnull);
223         }
224
225         override protected void SetStorage(object store, BitArray nullbits) {
226             values = (DateTime[]) store; 
227             SetNullStorage(nullbits);
228             if (DateTimeMode == DataSetDateTime.UnspecifiedLocal) {
229                 for (int i = 0; i < values.Length; i++) {
230                     if (HasValue(i)) {
231                         values[i] = DateTime.SpecifyKind(values[i].ToLocalTime(), DateTimeKind.Unspecified); //Strip the kind for UnspecifiedLocal.
232                     }
233                 }                
234             }
235             else if (DateTimeMode == DataSetDateTime.Local) {
236                 for (int i = 0; i < values.Length; i++) {
237                     if (HasValue(i)) {
238                         values[i] = values[i].ToLocalTime();
239                     }
240                 }                
241             }
242         }
243     }
244 }