1 //------------------------------------------------------------------------------
2 // <copyright file="DateTimeStorage.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 // <owner current="false" primary="false">[....]</owner>
8 //------------------------------------------------------------------------------
10 namespace System.Data.Common {
13 using System.Data.SqlTypes;
14 using System.Collections;
16 internal sealed class DateTimeStorage : DataStorage {
18 private static readonly DateTime defaultValue = DateTime.MinValue;
20 private DateTime[] values;
22 internal DateTimeStorage(DataColumn column)
23 : base(column, typeof(DateTime), defaultValue, StorageType.DateTime) {
26 override public Object Aggregate(int[] records, AggregateType 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;
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;
58 case AggregateType.First:
59 if (records.Length > 0) {
60 return values[records[0]];
64 case AggregateType.Count:
66 for (int i = 0; i < records.Length; i++) {
67 if (HasValue(records[i])) {
74 catch (OverflowException) {
75 throw ExprException.Overflow(typeof(DateTime));
77 throw ExceptionBuilder.AggregateException(kind, DataType);
80 override public int Compare(int recordNo1, int recordNo2) {
81 DateTime valueNo1 = values[recordNo1];
82 DateTime valueNo2 = values[recordNo2];
84 if (valueNo1 == defaultValue || valueNo2 == defaultValue) {
85 int bitCheck = CompareBits(recordNo1, recordNo2);
90 return DateTime.Compare(valueNo1, valueNo2);
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");
97 if (NullValue == value) {
98 return (HasValue(recordNo) ? 1 : 0);
101 DateTime valueNo1 = values[recordNo];
102 if ((defaultValue == valueNo1) && !HasValue(recordNo)) {
105 return DateTime.Compare(valueNo1, (DateTime)value);
108 public override object ConvertValue(object value) {
109 if (NullValue != value) {
111 value = ((IConvertible)value).ToDateTime(FormatProvider);
120 override public void Copy(int recordNo1, int recordNo2) {
121 CopyBits(recordNo1, recordNo2);
122 values[recordNo2] = values[recordNo1];
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)) {
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);
142 DateTime tmpValue = ((IConvertible)value).ToDateTime(FormatProvider);
143 switch (DateTimeMode) {
144 case DataSetDateTime.Utc:
145 if (tmpValue.Kind == DateTimeKind.Utc) {
148 else if (tmpValue.Kind == DateTimeKind.Local) {
149 retVal = tmpValue.ToUniversalTime();
152 retVal = DateTime.SpecifyKind(tmpValue, DateTimeKind.Utc);
155 case DataSetDateTime.Local:
156 if (tmpValue.Kind == DateTimeKind.Local) {
159 else if (tmpValue.Kind == DateTimeKind.Utc) {
160 retVal = tmpValue.ToLocalTime();
163 retVal = DateTime.SpecifyKind(tmpValue, DateTimeKind.Local);
166 case DataSetDateTime.Unspecified:
167 case DataSetDateTime.UnspecifiedLocal:
168 retVal = DateTime.SpecifyKind(tmpValue, DateTimeKind.Unspecified);
171 throw ExceptionBuilder.InvalidDateTimeMode(DateTimeMode);
173 values[record] = retVal;
174 SetNullBit(record, false);
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));
184 base.SetCapacity(capacity);
187 override public object ConvertXmlToObject(string s) {
189 if (DateTimeMode == DataSetDateTime.UnspecifiedLocal) {
190 retValue = XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.Unspecified);
193 retValue = XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind);
198 override public string ConvertObjectToXml(object value) {
200 if (DateTimeMode == DataSetDateTime.UnspecifiedLocal) {
201 retValue = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Local);
204 retValue = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
209 override protected object GetEmptyStorage(int recordCount) {
210 return new DateTime[recordCount];
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
220 typedStore[storeIndex] = values[record].ToUniversalTime();
222 nullbits.Set(storeIndex, isnull);
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++) {
231 values[i] = DateTime.SpecifyKind(values[i].ToLocalTime(), DateTimeKind.Unspecified); //Strip the kind for UnspecifiedLocal.
235 else if (DateTimeMode == DataSetDateTime.Local) {
236 for (int i = 0; i < values.Length; i++) {
238 values[i] = values[i].ToLocalTime();