18 using System.Globalization;
20 namespace Deveel.Data.Sql.Objects {
22 private readonly DateTimeOffset?
value;
26 private const int DateSize = 7;
27 private const int TimeStampSize = 11;
28 private const int FullTimeStampSize = 13;
30 public static readonly
string[] SqlDateFormats =
new[] {
35 public static readonly
string[] SqlTimeStampFormats =
new[] {
36 "yyyy-MM-dd HH:mm:ss.fff",
37 "yyyy-MM-dd HH:mm:ss.fff z",
38 "yyyy-MM-dd HH:mm:ss.fff zz",
39 "yyyy-MM-dd HH:mm:ss.fff zzz",
40 "yyyy-MM-dd HH:mm:ss",
41 "yyyy-MM-dd HH:mm:ss z",
42 "yyyy-MM-dd HH:mm:ss zz",
43 "yyyy-MM-dd HH:mm:ss zzz",
45 "yyyy-MM-ddTHH:mm:ss.fff",
46 "yyyy-MM-ddTHH:mm:ss.fff z",
47 "yyyy-MM-ddTHH:mm:ss.fff zz",
48 "yyyy-MM-ddTHH:mm:ss.fff zzz",
49 "yyyy-MM-ddTHH:mm:ss",
50 "yyyy-MM-ddTHH:mm:ss z",
51 "yyyy-MM-ddTHH:mm:ss zz",
52 "yyyy-MM-ddTHH:mm:ss zzz",
55 public static readonly
string[] SqlTimeFormats =
new[] {
66 public const string TimeStringFormat =
"HH:mm:ss.fff zzz";
67 public const string TimeStampStringFormat =
"yyyy-MM-ddTHH:mm:ss.fff zzz";
68 public const string DateStringFormat =
"yyyy-MM-dd";
77 public SqlDateTime(
int year,
int month,
int day,
int hour,
int minute,
int second,
int millisecond)
78 : this(year, month, day, hour, minute, second, millisecond,
SqlDayToSecond.Zero) {
83 if (year <= 0 || year > 9999)
84 throw new ArgumentOutOfRangeException(
"year");
85 if (month <= 0 || month > 12)
86 throw new ArgumentOutOfRangeException(
"month");
87 if (day <= 0 || day > 31)
88 throw new ArgumentOutOfRangeException(
"day");
90 if (hour < 0 || hour > 23)
91 throw new ArgumentOutOfRangeException(
"hour");
92 if (minute < 0 || minute > 59)
93 throw new ArgumentOutOfRangeException(
"minute");
94 if (second < 0 || second > 59)
95 throw new ArgumentOutOfRangeException(
"second");
96 if (millisecond < 0 || millisecond > 999)
97 throw new ArgumentOutOfRangeException(
"millisecond");
99 var tsOffset =
new TimeSpan(0, offset.
Hours, offset.
Minutes, 0, 0);
100 value =
new DateTimeOffset(year, month, day, hour, minute, second, millisecond, tsOffset);
109 var tsOffset =
new TimeSpan(0, offset.
Hours, offset.
Minutes, 0);
110 value =
new DateTimeOffset(ticks, tsOffset);
121 var year = ((bytes[0] - 100)*100) + (bytes[1] - 100);
122 var month = (int) bytes[2];
123 var day = (int) bytes[3];
124 var hour = (int) bytes[4] - 1;
125 var minute = (int)bytes[5] - 1;
126 var second = (int)bytes[6] - 1;
128 int tzh = 0, tzm = 0;
130 if (bytes.Length == DateSize) {
133 millis = bytes[7] << 24 | bytes[8] << 16 | bytes[9] << 8 | bytes[10];
134 if (bytes.Length == TimeStampSize) {
137 tzh = bytes[11] - 20;
138 tzm = bytes[12] - 60;
142 value =
new DateTimeOffset(year, month, day, hour, minute, second, millis,
new TimeSpan(0, tzh, tzm, 0, 0));
145 int IComparable.CompareTo(
object obj) {
154 get {
return value == null; }
159 throw new InvalidOperationException();
165 return value.Value.Year;
172 return value.Value.Month;
179 return value.Value.Day;
186 return value.Value.Hour;
193 return value.Value.Minute;
200 return value.Value.Second;
204 public int Millisecond {
207 return value.Value.Millisecond;
217 return new SqlDayToSecond(0, value.Value.Offset.Hours, value.Value.Offset.Minutes, 0, 0);
223 var date = DateTimeOffset.
Now;
224 var offset =
new SqlDayToSecond(date.Offset.Days, date.Offset.Hours, date.Offset.Minutes, date.Minute);
225 return new SqlDateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond, offset);
234 return TypeCode.DateTime;
237 bool IConvertible.ToBoolean(IFormatProvider provider) {
238 throw new InvalidCastException();
241 char IConvertible.ToChar(IFormatProvider provider) {
242 throw new InvalidCastException();
245 sbyte IConvertible.ToSByte(IFormatProvider provider) {
246 throw new NotImplementedException();
249 byte IConvertible.ToByte(IFormatProvider provider) {
250 throw new InvalidCastException();
253 short IConvertible.ToInt16(IFormatProvider provider) {
254 throw new InvalidCastException();
257 ushort IConvertible.ToUInt16(IFormatProvider provider) {
258 throw new InvalidCastException();
261 int IConvertible.ToInt32(IFormatProvider provider) {
262 throw new InvalidCastException();
265 uint IConvertible.ToUInt32(IFormatProvider provider) {
266 throw new InvalidCastException();
269 long IConvertible.ToInt64(IFormatProvider provider) {
273 ulong IConvertible.ToUInt64(IFormatProvider provider) {
274 return (ulong) ToInt64();
277 float IConvertible.ToSingle(IFormatProvider provider) {
281 double IConvertible.ToDouble(IFormatProvider provider) {
285 decimal IConvertible.ToDecimal(IFormatProvider provider) {
286 throw new NotImplementedException();
289 DateTime IConvertible.ToDateTime(IFormatProvider provider) {
291 throw new NullReferenceException();
293 return value.Value.DateTime;
296 string IConvertible.ToString(IFormatProvider provider) {
300 object IConvertible.ToType(Type conversionType, IFormatProvider provider) {
301 if (conversionType == typeof (
long))
303 if (conversionType == typeof (
float))
304 return (
float) ToInt64();
305 if (conversionType == typeof (
double))
306 return (
double) ToInt64();
308 if (conversionType == typeof (
string))
311 if (conversionType == typeof (byte[]))
312 return ToByteArray();
314 throw new InvalidCastException();
318 if (IsNull && other.
IsNull)
321 return value.Equals(other.
value);
324 public override bool Equals(
object obj) {
329 return value == null ? 0 : value.GetHashCode();
333 if (!value.HasValue && !other.
value.HasValue)
337 if (!other.
value.HasValue)
340 return value.Value.CompareTo(other.
value.Value);
345 return value.Value.Ticks;
349 return ToByteArray(
false);
353 var size = timeZone ? 13 : 11;
355 return new byte[size];
357 var bytes =
new byte[size];
358 bytes[0] = (byte)((Year / 100) + 100);
359 bytes[1] = (byte)((Year % 100) + 100);
360 bytes[2] = (byte)(Month);
361 bytes[3] = (byte)(Day);
362 bytes[4] = (byte)(Hour + 1);
363 bytes[5] = (byte)(Minute + 1);
364 bytes[6] = (byte)(Second + 1);
365 bytes[7] = (byte)((Millisecond >> 24));
366 bytes[8] = (byte)((Millisecond >> 16) & 0xff);
367 bytes[9] = (byte)((Millisecond >> 8) & 0xff);
368 bytes[10]= (byte)(Millisecond & 0xff);
370 var tsOffset = Offset;
371 bytes[11] = (byte)(tsOffset.Hours + 20);
372 bytes[12] = (byte)(tsOffset.Minutes + 60);
431 var result = value.Value.AddMonths(interval.
TotalMonths);
441 var result = value.Value.AddMonths(-interval.
TotalMonths);
463 return i == 0 || i > 0;
468 return i == 0 || i < 0;
489 if (!TryParse(s, out date))
490 throw new FormatException(String.Format(
"Cannot convert string {0} to a valid SQL DATE", s));
497 if (TryParseDate(s, out value))
500 if (TryParseTime(s, out value))
503 if (TryParseTimeStamp(s, out value))
515 if (DateTimeOffset.TryParseExact(s, SqlDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) {
528 if (DateTimeOffset.TryParseExact(s, SqlTimeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) {
529 var offset =
new SqlDayToSecond(date.Offset.Hours, date.Offset.Minutes,0);
530 value =
new SqlDateTime(1, 1, 1, date.Hour, date.Minute, date.Second, date.Millisecond, offset);
542 if (DateTimeOffset.TryParseExact(s, SqlTimeStampFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) {
543 var offset =
new SqlDayToSecond(date.Offset.Hours, date.Offset.Minutes, 0);
544 value =
new SqlDateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond, offset);
560 var offset =
new SqlDayToSecond(date.Offset.Days, date.Offset.Hours, date.Offset.Minutes, date.Offset.Seconds);
561 return new SqlDateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond, offset);
565 if (a == null || a.IsNull)
568 var offset =
new TimeSpan(a.Offset.Hours, a.Offset.Minutes, a.Offset.Seconds);
569 return new DateTimeOffset(a.Year, a.Month, a.Day, a.Hour, a.Minute, a.Second, a.Millisecond, offset);
573 if (a == null || a.
IsNull)
574 throw new NullReferenceException();
584 var utc = value.Value.ToUniversalTime();
585 var offset =
new SqlDayToSecond(utc.Offset.Days, utc.Offset.Hours, utc.Offset.Minutes);
586 return new SqlDateTime(utc.Year, utc.Month, utc.Day, utc.Hour, utc.Minute, utc.Second, utc.Millisecond, offset);
593 var s = value.Value.ToString(DateStringFormat, CultureInfo.InvariantCulture);
601 var s = value.Value.ToString(TimeStringFormat, CultureInfo.InvariantCulture);
609 var s = value.Value.ToString(TimeStampStringFormat, CultureInfo.InvariantCulture);
617 return ToTimeStampString().ToString();
622 throw new InvalidCastException();
624 return value.Value.DateTime;
SqlDateTime Add(SqlYearToMonth interval)
Adds the given months to this date.
SqlDayToSecond Offset
Gets the offset between the date-time instance and the UTC time.
override string ToString()
int CompareTo(SqlDateTime other)
static bool TryParseTimeStamp(string s, out SqlDateTime value)
SqlDateTime Add(SqlDayToSecond interval)
Adds the given interval of time to this date-time.
byte[] ToByteArray(bool timeZone)
readonly DateTimeOffset value
static bool TryParseTime(string s, out SqlDateTime value)
SqlDateTime(long ticks, SqlDayToSecond offset)
override bool Equals(object obj)
SqlDateTime(int year, int month, int day)
SqlDateTime(byte[] bytes)
static readonly SqlDayToSecond Zero
Defines the contract for a valid SQL Object
int IComparable. CompareTo(object obj)
static SqlDateTime Parse(string s)
TypeCode IConvertible. GetTypeCode()
static bool TryParseDate(string s, out SqlDateTime value)
bool IsComparableTo(ISqlObject other)
Checks if the current object is comparable with the given one.
bool Equals(SqlDateTime other)
int TotalMonths
Gets the total number of months that represents the time span.
SqlDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond)
A month span representation of time.
SqlDateTime Subtract(SqlDayToSecond interval)
Subtracts a given interval of time from this date.
SqlDateTime Subtract(SqlYearToMonth interval)
static bool TryParse(string s, out SqlDateTime value)
Deveel.Data.Sql.Objects.SqlString SqlString
SqlString ToTimeStampString()
SqlDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, SqlDayToSecond offset)
override int GetHashCode()