/// <summary> /// Ignores miliseconds in the datetime provided and then asserts it against the expected DateTime /// value /// </summary> /// <param name="expectedDateTime"></param> /// <param name="actualDateTime"></param> public static void AssertNullableDateTime(DateTime?expectedDateTime, DateTime?actualDateTime) { actualDateTime = actualDateTime?.AddTicks(-actualDateTime.Value.Ticks % TimeSpan.TicksPerSecond); expectedDateTime = expectedDateTime?.AddTicks(-expectedDateTime.Value.Ticks % TimeSpan.TicksPerSecond); if (!expectedDateTime.Equals(actualDateTime)) { throw new InvalidOperationException("The expected DateTime and actual DateTime are not equal"); } }
/// <summary> /// Gets a random DateTime value of the specified kind, by default within SQL-safe range /// </summary> /// <param name="kind">DateTimeKind required for this value</param> /// <param name="minDate">Minimum date to consider</param> /// <param name="maxDate">Maximum date to consider</param> /// <param name="dateOnly">Flag to determine if times should be truncated</param> /// <param name="minTime">Minimum time to consider (default all)</param> /// <param name="maxTime">Maximum time to consider (default all)</param> /// <returns>Random DateTime value of the specified kind, within the specified range</returns> // ReSharper disable once MemberCanBePrivate.Global public static DateTime GetRandomDate( DateTimeKind kind, DateTime?minDate = null, DateTime?maxDate = null, bool dateOnly = false, DateTime?minTime = null, DateTime?maxTime = null ) { var dateRangeLower = new DateTime(1990, 1, 1); const int dateRangeYears = 30; if (dateOnly) { minDate = minDate?.AddTicks(-1).AddDays(1).StartOfDay(); maxDate = maxDate?.StartOfDay().AddDays(1).AddTicks(-1); if (minDate > maxDate) { minDate = minDate.Value.AddDays(-1); } } var minTicks = (minDate ?? maxDate?.AddYears(-dateRangeYears) ?? dateRangeLower).Ticks; var maxTicks = (maxDate ?? new DateTime(minTicks).AddYears(dateRangeYears)).Ticks; var actualTicks = GetRandomLong(minTicks, maxTicks); var rawDateTime = new DateTime(actualTicks); var sanitised = new DateTime( rawDateTime.Year, rawDateTime.Month, rawDateTime.Day, rawDateTime.Hour, rawDateTime.Minute, rawDateTime.Second, rawDateTime.Millisecond, kind); return(dateOnly ? sanitised.StartOfDay() : RangeCheckTimeOnRandomDate(minTime, maxTime, sanitised)); }
private void InitiateXsdDateTime(Parser parser) { dt = new DateTime(parser.year, parser.month, parser.day, parser.hour, parser.minute, parser.second); if (parser.fraction != 0) { dt = dt.AddTicks(parser.fraction); } extra = (uint)(((int)parser.typeCode << TypeShift) | ((int)parser.kind << KindShift) | (parser.zoneHour << ZoneHourShift) | parser.zoneMinute); }
public void CanAddTicksAcrossDstTransition() { var tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); var dt = new DateTime(2015, 3, 8, 1, 59, 59, 999).AddTicks(9999); var result = dt.AddTicks(1, tz); var expected = new DateTimeOffset(2015, 3, 8, 3, 0, 0, TimeSpan.FromHours(-7)); Assert.Equal(expected, result); Assert.Equal(expected.Offset, result.Offset); }
//[Variation("ToString(DateTime,XmlDateTimeSerializationMode.Local) - valid cases")] public int ToType43() { DateTime dtLocal = new DateTime(); // DateTime DateTime dt = new DateTime(2002, 12, 30, 23, 15, 55, 100); string expDateTime = (TimeZoneInfo.Local.GetUtcOffset(dt).Hours < 0) ? String.Format("2002-12-30T23:15:55.1-0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)) : String.Format("2002-12-30T23:15:55.1+0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)); CError.Equals(XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Local), expDateTime, "datetime1"); dt = new DateTime(1, 1, 1, 23, 59, 59); dt = dt.AddTicks(9999999); expDateTime = (TimeZoneInfo.Local.GetUtcOffset(dt).Hours < 0) ? String.Format("0001-01-01T23:59:59.9999999-0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)) : String.Format("0001-01-01T23:59:59.9999999+0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)); CError.Equals(XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Local), expDateTime, "milisecs"); // new 05/2002 dt = new DateTime(2002, 12, 30, 23, 15, 55); expDateTime = (TimeZoneInfo.Local.GetUtcOffset(dt).Hours < 0) ? String.Format("2002-12-30T23:15:55-0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)) : String.Format("2002-12-30T23:15:55+0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)); CError.Equals(XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Local), expDateTime, "datetime2"); // Read in Universal Time dt = new DateTime(); dtLocal = XmlConvert.ToDateTime("2002-12-31T07:15:55.0000000Z", XmlDateTimeSerializationMode.Local); // this is just to get the offset dt = XmlConvert.ToDateTime("2002-12-31T07:15:55.0000000Z", XmlDateTimeSerializationMode.RoundtripKind); if (TimeZoneInfo.Local.GetUtcOffset(dt).Hours == -8 || TimeZoneInfo.Local.GetUtcOffset(dt).Hours == 9) { // only -08:00 and 09:00 works expDateTime = (TimeZoneInfo.Local.GetUtcOffset(dt).Hours < 0) ? String.Format("2002-12-30T23:15:55-0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dtLocal).Hours)) : String.Format("2002-12-31T16:15:55+0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dtLocal).Hours)); CError.Equals(XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Local), expDateTime, "Read in Universal Time"); } // Read in Local Time dt = new DateTime(); dt = XmlConvert.ToDateTime("2002-12-31T07:15:55.0000000-00:00", XmlDateTimeSerializationMode.RoundtripKind); if (TimeZoneInfo.Local.GetUtcOffset(dt).Hours == -8 || TimeZoneInfo.Local.GetUtcOffset(dt).Hours == 9) { // only -08:00 and 09:00 works expDateTime = (TimeZoneInfo.Local.GetUtcOffset(dt).Hours < 0) ? String.Format("2002-12-30T23:15:55-0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)) : String.Format("2002-12-31T16:15:55+0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)); CError.Equals(XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Local), expDateTime, "Read in Local Time"); } // Read in Unspecified Time dt = new DateTime(); dt = XmlConvert.ToDateTime("2002-12-31T07:15:55.0000000", XmlDateTimeSerializationMode.RoundtripKind); expDateTime = (TimeZoneInfo.Local.GetUtcOffset(dt).Hours < 0) ? String.Format("2002-12-31T07:15:55-0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)) : String.Format("2002-12-31T07:15:55+0{0}:00", Math.Abs(TimeZoneInfo.Local.GetUtcOffset(dt).Hours)); CError.Equals(XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Local), expDateTime, "Read in UnSpecified Time"); return TEST_PASS; }
/// <summary> /// ToString(DateTime) - valid cases. Need to disable for warning /// </summary> /// <returns></returns> #pragma warning disable 618 public int ToType40() { var dt = new DateTime(2002, 12, 30, 23, 15, 55, 100); TimeSpan span = TimeZoneInfo.Local.GetUtcOffset(dt); string expDateTime = String.Format("2002-12-30T23:15:55.1{0:+0#;-0#}:{1:00}", span.Hours, span.Minutes); CError.Compare(XmlConvert.ToString(dt), expDateTime, "datetime"); dt = new DateTime(1, 1, 1, 23, 59, 59); dt = dt.AddTicks(9999999); span = TimeZoneInfo.Local.GetUtcOffset(dt); expDateTime = String.Format("0001-01-01T23:59:59.9999999{0:+0#;-0#}:{1:00}", span.Hours, span.Minutes); CError.Compare(XmlConvert.ToString(dt), expDateTime, "milisecs"); dt = new DateTime(2002, 12, 30, 23, 15, 55); span = TimeZoneInfo.Local.GetUtcOffset(dt); expDateTime = String.Format("2002-12-30T23:15:55{0:+0#;-0#}:{1:00}", span.Hours, span.Minutes); CError.Compare(XmlConvert.ToString(dt), expDateTime, "datetime"); dt = new DateTime(2002, 12, 30, 23, 15, 55, 0); CError.Compare(XmlConvert.ToString(dt, "HH:mm:ss"), "23:15:55", "datetime"); dt = new DateTime(2002, 12, 30, 23, 15, 55, 0); CError.Compare(XmlConvert.ToString(dt, "HH:mm:ssZ"), "23:15:55Z", "datetime"); dt = new DateTime(2002, 12, 30, 23, 15, 55, 0); CError.Compare(XmlConvert.ToString(dt, "yyyy-MM-dd"), "2002-12-30", "datetime"); return TEST_PASS; }
/// <summary> /// Removes the milliseconds from the date. CRM doesn't store milliseconds, so this is used frequently when working with dates. /// </summary> /// <param name="date">The date.</param> /// <returns></returns> public static DateTime?RemoveMilliseconds(this DateTime?date) { return(date?.AddTicks(-(date.Value.Ticks % TimeSpan.TicksPerSecond))); }
private static DateTimeOffset ConvertDateTimeOffsetLiteralValue(ErrorContext errCtx, string datetimeLiteralValue) { var datetimeParts = datetimeLiteralValue.Split(_datetimeOffsetSeparators, StringSplitOptions.RemoveEmptyEntries); Debug.Assert(datetimeParts.Length >= 7, "datetime literal value must have at least 7 parts"); int year; int month; int day; GetDateParts(datetimeLiteralValue, datetimeParts, out year, out month, out day); int hour; int minute; int second; int ticks; //Copy the time parts into a different array since the last two parts will be handled in this method. var timeParts = new String[datetimeParts.Length - 2]; Array.Copy(datetimeParts, timeParts, datetimeParts.Length - 2); GetTimeParts(datetimeLiteralValue, timeParts, 3, out hour, out minute, out second, out ticks); Debug.Assert(year >= 1 && year <= 9999); Debug.Assert(month >= 1 && month <= 12); Debug.Assert(day >= 1 && day <= 31); Debug.Assert(hour >= 0 && hour <= 24); Debug.Assert(minute >= 0 && minute <= 59); Debug.Assert(second >= 0 && second <= 59); Debug.Assert(ticks >= 0 && ticks <= 9999999); var offsetHours = Int32.Parse(datetimeParts[datetimeParts.Length - 2], NumberStyles.Integer, CultureInfo.InvariantCulture); var offsetMinutes = Int32.Parse(datetimeParts[datetimeParts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture); var offsetTimeSpan = new TimeSpan(offsetHours, offsetMinutes, 0); //If DateTimeOffset had a negative offset, we should negate the timespan if (datetimeLiteralValue.IndexOf('+') == -1) { offsetTimeSpan = offsetTimeSpan.Negate(); } var dateTime = new DateTime(year, month, day, hour, minute, second, 0); dateTime = dateTime.AddTicks(ticks); try { return new DateTimeOffset(dateTime, offsetTimeSpan); } catch (ArgumentOutOfRangeException e) { var message = Strings.InvalidDateTimeOffsetLiteral(datetimeLiteralValue); throw EntitySqlException.Create(errCtx, message, e); } }
/// <summary> /// Converts datetime literal value. /// </summary> private static DateTime ConvertDateTimeLiteralValue(string datetimeLiteralValue) { var datetimeParts = datetimeLiteralValue.Split(_datetimeSeparators, StringSplitOptions.RemoveEmptyEntries); Debug.Assert(datetimeParts.Length >= 5, "datetime literal value must have at least 5 parts"); int year; int month; int day; GetDateParts(datetimeLiteralValue, datetimeParts, out year, out month, out day); int hour; int minute; int second; int ticks; GetTimeParts(datetimeLiteralValue, datetimeParts, 3, out hour, out minute, out second, out ticks); Debug.Assert(year >= 1 && year <= 9999); Debug.Assert(month >= 1 && month <= 12); Debug.Assert(day >= 1 && day <= 31); Debug.Assert(hour >= 0 && hour <= 24); Debug.Assert(minute >= 0 && minute <= 59); Debug.Assert(second >= 0 && second <= 59); Debug.Assert(ticks >= 0 && ticks <= 9999999); var dateTime = new DateTime(year, month, day, hour, minute, second, 0); dateTime = dateTime.AddTicks(ticks); return dateTime; }
static DateTime Mid(DateTime d1, DateTime d2) { return(d1.AddTicks((d2 - d1).Ticks / 2)); }
public static DateTime TicksToDateTime(this long ticks) => MinDateTimeJS.AddTicks(ticks);
internal static bool TryParseDateIso(string text, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, out object dt) { DateTimeParser dateTimeParser = new DateTimeParser(); if (!dateTimeParser.Parse(text)) { dt = null; return(false); } DateTime d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second); d = d.AddTicks(dateTimeParser.Fraction); #if !NET20 if (dateParseHandling == DateParseHandling.DateTimeOffset) { TimeSpan offset; switch (dateTimeParser.Zone) { case ParserTimeZone.Utc: offset = new TimeSpan(0L); break; case ParserTimeZone.LocalWestOfUtc: offset = new TimeSpan(-dateTimeParser.ZoneHour, -dateTimeParser.ZoneMinute, 0); break; case ParserTimeZone.LocalEastOfUtc: offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); break; default: offset = TimeZoneInfo.Local.GetUtcOffset(d); break; } long ticks = d.Ticks - offset.Ticks; if (ticks < 0 || ticks > 3155378975999999999) { dt = null; return(false); } dt = new DateTimeOffset(d, offset); return(true); } else #endif { long ticks; switch (dateTimeParser.Zone) { case ParserTimeZone.Utc: d = new DateTime(d.Ticks, DateTimeKind.Utc); break; case ParserTimeZone.LocalWestOfUtc: { TimeSpan offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); ticks = d.Ticks + offset.Ticks; if (ticks <= DateTime.MaxValue.Ticks) { d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime(); } else { ticks += d.GetUtcOffset().Ticks; if (ticks > DateTime.MaxValue.Ticks) { ticks = DateTime.MaxValue.Ticks; } d = new DateTime(ticks, DateTimeKind.Local); } break; } case ParserTimeZone.LocalEastOfUtc: { TimeSpan offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); ticks = d.Ticks - offset.Ticks; if (ticks >= DateTime.MinValue.Ticks) { d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime(); } else { ticks += d.GetUtcOffset().Ticks; if (ticks < DateTime.MinValue.Ticks) { ticks = DateTime.MinValue.Ticks; } d = new DateTime(ticks, DateTimeKind.Local); } break; } } dt = EnsureDateTime(d, dateTimeZoneHandling); return(true); } }
public static DateTime Round(DateTime value, long resolution) { return(value.AddTicks(-(value.Ticks % resolution))); }
// This data serves as inputs to converting from CLR types that a developer // would use in his app to a given json serialized format using the spanner type // to determine how to serialize. // The inputs are used to test both ways (also deseralizing the generated json // to a requested clr type). However some cases are specified as only one direction // usually because the conversion is by definition lossy. public static IEnumerable <object[]> GetValidValueConversions() { // Format is: LocalClrInstance, SpannerType, SerializedJsonFromProto, [test one or both ways] // Testing can be one way if there is loss of information in the conversion. // Spanner type = Float64 tests. yield return(new object[] { true, SpannerDbType.Float64, "1" }); yield return(new object[] { false, SpannerDbType.Float64, "0" }); yield return(new object[] { (byte)1, SpannerDbType.Float64, "1" }); yield return(new object[] { (sbyte)1, SpannerDbType.Float64, "1" }); yield return(new object[] { 1.5M, SpannerDbType.Float64, "1.5" }); yield return(new object[] { 1.5D, SpannerDbType.Float64, "1.5" }); yield return(new object[] { 1.5F, SpannerDbType.Float64, "1.5" }); yield return(new object[] { double.NegativeInfinity, SpannerDbType.Float64, Quote("-Infinity") }); yield return(new object[] { double.PositiveInfinity, SpannerDbType.Float64, Quote("Infinity") }); yield return(new object[] { double.NaN, SpannerDbType.Float64, Quote("NaN") }); yield return(new object[] { 1, SpannerDbType.Float64, "1" }); yield return(new object[] { 1U, SpannerDbType.Float64, "1" }); yield return(new object[] { 1L, SpannerDbType.Float64, "1" }); yield return(new object[] { (ulong)1, SpannerDbType.Float64, "1" }); yield return(new object[] { (short)1, SpannerDbType.Float64, "1" }); yield return(new object[] { (ushort)1, SpannerDbType.Float64, "1" }); yield return(new object[] { "1", SpannerDbType.Float64, "1" }); yield return(new object[] { "1.5", SpannerDbType.Float64, "1.5" }); yield return(new object[] { DBNull.Value, SpannerDbType.Float64, "null" }); // Spanner type = Int64 tests. yield return(new object[] { true, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { false, SpannerDbType.Int64, Quote("0") }); yield return(new object[] { (char)1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { (byte)1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { (sbyte)1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { 2M, SpannerDbType.Int64, Quote("2") }); yield return(new object[] { 1.5M, SpannerDbType.Int64, Quote("2"), TestType.ClrToValue }); yield return(new object[] { 2D, SpannerDbType.Int64, Quote("2") }); yield return(new object[] { 1.5D, SpannerDbType.Int64, Quote("2"), TestType.ClrToValue }); yield return(new object[] { 2F, SpannerDbType.Int64, Quote("2") }); yield return(new object[] { 1.5F, SpannerDbType.Int64, Quote("2"), TestType.ClrToValue }); yield return(new object[] { 1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { 1U, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { 1L, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { (ulong)1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { (short)1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { (ushort)1, SpannerDbType.Int64, Quote("1") }); yield return(new object[] { "1", SpannerDbType.Int64, Quote("1") }); // Spanner type = Bool tests. yield return(new object[] { true, SpannerDbType.Bool, "true" }); yield return(new object[] { false, SpannerDbType.Bool, "false" }); yield return(new object[] { (byte)1, SpannerDbType.Bool, "true" }); yield return(new object[] { (byte)0, SpannerDbType.Bool, "false" }); yield return(new object[] { (sbyte)1, SpannerDbType.Bool, "true" }); yield return(new object[] { (sbyte)0, SpannerDbType.Bool, "false" }); yield return(new object[] { 1M, SpannerDbType.Bool, "true" }); yield return(new object[] { 6.5M, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { 0M, SpannerDbType.Bool, "false" }); yield return(new object[] { 1D, SpannerDbType.Bool, "true" }); yield return(new object[] { 6.5D, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { 0D, SpannerDbType.Bool, "false" }); yield return(new object[] { 1F, SpannerDbType.Bool, "true" }); yield return(new object[] { 6.5F, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { 0F, SpannerDbType.Bool, "false" }); yield return(new object[] { 1, SpannerDbType.Bool, "true" }); yield return(new object[] { 11, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { 0, SpannerDbType.Bool, "false" }); yield return(new object[] { 1U, SpannerDbType.Bool, "true" }); yield return(new object[] { 100U, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { 0U, SpannerDbType.Bool, "false" }); yield return(new object[] { 1L, SpannerDbType.Bool, "true" }); yield return(new object[] { -1L, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { 0L, SpannerDbType.Bool, "false" }); yield return(new object[] { (ulong)1, SpannerDbType.Bool, "true" }); yield return(new object[] { (ulong)21, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { (ulong)0, SpannerDbType.Bool, "false" }); yield return(new object[] { (short)1, SpannerDbType.Bool, "true" }); yield return(new object[] { (short)-1, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { (short)0, SpannerDbType.Bool, "false" }); yield return(new object[] { (ushort)1, SpannerDbType.Bool, "true" }); yield return(new object[] { (ushort)11, SpannerDbType.Bool, "true", TestType.ClrToValue }); yield return(new object[] { (ushort)0, SpannerDbType.Bool, "false" }); // Spanner type = String tests. // Note the casing on bool->string follows c# bool conversion semantics (by design). yield return(new object[] { true, SpannerDbType.String, Quote("True") }); yield return(new object[] { false, SpannerDbType.String, Quote("False") }); yield return(new object[] { (char)26, SpannerDbType.String, Quote("\\u001a") }); yield return(new object[] { (byte)1, SpannerDbType.String, Quote("1") }); yield return(new object[] { (sbyte)1, SpannerDbType.String, Quote("1") }); yield return(new object[] { 1.5M, SpannerDbType.String, Quote("1.5") }); yield return(new object[] { 1.5D, SpannerDbType.String, Quote("1.5") }); yield return(new object[] { 1.5F, SpannerDbType.String, Quote("1.5") }); yield return(new object[] { 1, SpannerDbType.String, Quote("1") }); yield return(new object[] { 1U, SpannerDbType.String, Quote("1") }); yield return(new object[] { 1L, SpannerDbType.String, Quote("1") }); yield return(new object[] { (ulong)1, SpannerDbType.String, Quote("1") }); yield return(new object[] { (short)1, SpannerDbType.String, Quote("1") }); yield return(new object[] { (ushort)1, SpannerDbType.String, Quote("1") }); yield return(new object[] { s_testDate, SpannerDbType.String, Quote("2017-01-31T03:15:30.5Z") }); // Note the difference in C# conversions from special doubles. yield return(new object[] { double.NegativeInfinity, SpannerDbType.String, Quote("-Infinity") }); yield return(new object[] { double.PositiveInfinity, SpannerDbType.String, Quote("Infinity") }); yield return(new object[] { double.NaN, SpannerDbType.String, Quote("NaN") }); yield return(new object[] { "1.5", SpannerDbType.String, Quote("1.5") }); yield return(new object[] { new ToStringClass("hello"), SpannerDbType.String, Quote("hello"), TestType.ClrToValue }); // Spanner type = Date+Timestamp tests. Some of these are one way due to either a lossy conversion (date loses time) // or a string formatting difference. yield return(new object[] { s_testDate, SpannerDbType.Date, Quote("2017-01-31"), TestType.ClrToValue }); yield return(new object[] { "1/31/2017", SpannerDbType.Date, Quote("2017-01-31"), TestType.ClrToValue }); yield return(new object[] { "1/31/2017 3:15:30 AM", SpannerDbType.Date, Quote("2017-01-31"), TestType.ClrToValue }); yield return(new object[] { s_testDate, SpannerDbType.Timestamp, Quote("2017-01-31T03:15:30.5Z") }); yield return(new object[] { s_testDate.AddTicks(5), SpannerDbType.Timestamp, Quote("2017-01-31T03:15:30.5000005Z") }); yield return(new object[] { "1/31/2017", SpannerDbType.Timestamp, Quote("2017-01-31T00:00:00Z"), TestType.ClrToValue }); yield return(new object[] { "1/31/2017 3:15:30 AM", SpannerDbType.Timestamp, Quote("2017-01-31T03:15:30Z"), TestType.ClrToValue }); yield return(new object[] { "1/31/2017 3:15:30 AM", SpannerDbType.Timestamp, Quote("2017-01-31T03:15:30Z"), TestType.ClrToValue }); // Spanner type = Bytes tests. yield return(new object[] { s_base64Encoded, SpannerDbType.Bytes, Quote(s_base64Encoded) }); yield return(new object[] { s_bytesToEncode, SpannerDbType.Bytes, Quote(s_base64Encoded) }); yield return(new object[] { "passthrubadbytes", SpannerDbType.Bytes, Quote("passthrubadbytes") }); // List test cases (list of type X). yield return(new object[] { new List <string>(GetStringsForArray()), SpannerDbType.ArrayOf(SpannerDbType.String), "[ \"abc\", \"123\", \"def\" ]" }); yield return(new object[] { new List <double>(GetFloatsForArray()), SpannerDbType.ArrayOf(SpannerDbType.Float64), "[ 1, 2, 3 ]" }); yield return(new object[] { new List <int>(GetIntsForArray()), SpannerDbType.ArrayOf(SpannerDbType.Int64), "[ \"4\", \"5\", \"6\" ]" }); yield return(new object[] { new List <bool>(GetBoolsForArray()), SpannerDbType.ArrayOf(SpannerDbType.Bool), "[ true, false, true ]" }); yield return(new object[] { new List <DateTime>(GetDatesForArray()), SpannerDbType.ArrayOf(SpannerDbType.Date), "[ \"2017-01-31\", \"2016-02-15\", \"2015-03-31\" ]" }); yield return(new object[] { new List <DateTime>(GetTimestampsForArray()), SpannerDbType.ArrayOf(SpannerDbType.Timestamp), "[ \"2017-01-31T03:15:30.5Z\", \"2016-02-15T13:15:30Z\", \"2015-03-31T03:15:30.25Z\" ]" }); // List test cases (various source/target list types) yield return(new object[] { GetStringsForArray(), SpannerDbType.ArrayOf(SpannerDbType.String), "[ \"abc\", \"123\", \"def\" ]", TestType.ClrToValue }); yield return(new object[] { new ArrayList(GetStringsForArray().ToList()), SpannerDbType.ArrayOf(SpannerDbType.String), "[ \"abc\", \"123\", \"def\" ]" }); yield return(new object[] { new List <object>(GetStringsForArray()), SpannerDbType.ArrayOf(SpannerDbType.String), "[ \"abc\", \"123\", \"def\" ]" }); yield return(new object[] { new CustomList(GetStringsForArray()), SpannerDbType.ArrayOf(SpannerDbType.String), "[ \"abc\", \"123\", \"def\" ]" }); // List test cases with null entries yield return(new object[] { new List <string> { "x", null, "y" }, SpannerDbType.ArrayOf(SpannerDbType.String), "[ \"x\", null, \"y\" ]" }); yield return(new object[] { new double?[] { 5.5, null, 10.5 }, SpannerDbType.ArrayOf(SpannerDbType.Float64), "[ 5.5, null, 10.5 ]" }); // Struct test case includes nested complex conversions. // These are one-way only, because SpannerStruct doesn't (and can't generally) implement // IEquatable<T>. (By the time the nested value can be an array etc, it ends up being infeasible.) // Deserialization is therefore handled separately in hand-written tests. yield return(new object[] { s_sampleStruct, s_sampleStruct.GetSpannerDbType(), s_sampleStructSerialized, TestType.ClrToValue }); // Array of structs. yield return(new object[] { new List <object>(new[] { s_sampleStruct }), SpannerDbType.ArrayOf(s_sampleStruct.GetSpannerDbType()), $"[ {s_sampleStructSerialized} ]", TestType.ClrToValue }); // Struct of struct and array. var complexStruct = new SpannerStruct { { "StructField", s_sampleStruct.GetSpannerDbType(), s_sampleStruct }, { "ArrayField", SpannerDbType.ArrayOf(SpannerDbType.Int64), GetIntsForArray().Select(x => (long)x).ToList() } }; yield return(new object[] { complexStruct, complexStruct.GetSpannerDbType(), $"[ {s_sampleStructSerialized}, [ \"4\", \"5\", \"6\" ] ]", TestType.ClrToValue }); }
public static void AddTicks(DateTime dateTime, long ticks, DateTime expected) { Assert.Equal(expected, dateTime.AddTicks(ticks)); }
/// <summary> /// Truncate to the specified TimeSpan's magnitude. For example, to truncate to the nearest second, use TimeSpan.FromSeconds(1) /// </summary> /// <param name="dateTime"></param> /// <param name="timeSpan"></param> /// <returns></returns> public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) => timeSpan == TimeSpan.Zero ? dateTime : dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks));