Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,20 @@ public override void WriteValue(decimal value)
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
public override void WriteValue(DateTime value)
{
// We use rount trip format for datetime parsing and trim the additional trailing zeros using a custom "O" format
// We use round trip format for datetime parsing and trim the additional trailing zeros using a custom "O" format
// to maintain milliseconds precision.
this.WriteValue(
value.ToString(
format: CosmosDBToNewtonsoftWriter.RoundTripFormatWithoutTrailingZeros));
}

/// <summary>
/// Writes a <see cref="DateTimeOffset"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
public override void WriteValue(DateTimeOffset value)
{
// We use round trip format for datetime parsing and trim the additional trailing zeros using a custom "O" format
// to maintain milliseconds precision.
this.WriteValue(
value.ToString(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ public async Task TestGetPartitionKeyValueFromStreamAsync(bool binaryEncodingEna
cancellationToken));

DateTime dateTime = new DateTime(2019, 05, 15, 12, 1, 2, 3, DateTimeKind.Utc);
DateTimeOffset dateTimeOffset = new DateTimeOffset(2019, 05, 15, 12, 1, 2, 3, TimeSpan.Zero);
Guid guid = Guid.NewGuid();

//Test supported types
Expand All @@ -273,6 +274,7 @@ public async Task TestGetPartitionKeyValueFromStreamAsync(bool binaryEncodingEna
new { pk = char.MaxValue },
new { pk = "test" },
new { pk = dateTime },
new { pk = dateTimeOffset},
new { pk = guid },
};

Expand Down Expand Up @@ -308,6 +310,10 @@ public async Task TestGetPartitionKeyValueFromStreamAsync(bool binaryEncodingEna
{
Assert.AreEqual(poco.pk.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), stringValue);
}
else if (poco.pk is DateTimeOffset)
{
Assert.AreEqual(poco.pk.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), stringValue);
}
else
{
Assert.AreEqual(poco.pk.ToString(), (string)pk);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ public void AllPrimitivesObjectTest()
new JProperty("boolean", true),
new JProperty("null", null),
new JProperty("datetime", DateTime.Parse("2526-07-11T18:18:16.4520716")),
new JProperty("datetimeoffset", DateTimeOffset.Parse("2500-11-12T01:21:00+00:00")),
new JProperty("spatialPoint", new JObject(
new JProperty("type", "Point"),
new JProperty("coordinate", new double[] { 118.9897, -46.6781 }))),
Expand Down Expand Up @@ -272,6 +273,73 @@ public void AllDatetimeVariationsTest()
NewtonsoftInteropTests.VerifyNewtonsoftInterop<JObject>(jsonObject);
}

[TestMethod]
[Owner("mpalaparthi")]
public void AllDateTimeOffsetVariationsTest()
{
// Arrange
JObject jsonObject = new JObject();

// 1. Current UTC DateTimeOffset using JProperty
DateTimeOffset utcNow = DateTimeOffset.UtcNow;
JProperty utcNowProperty = new JProperty("currentUtcDateTimeOffset", utcNow);
jsonObject.Add(utcNowProperty);

// 2. Current Local DateTimeOffset using JProperty
DateTimeOffset localNow = DateTimeOffset.Now;
JProperty localNowProperty = new JProperty("currentLocalDateTimeOffset", localNow);
jsonObject.Add(localNowProperty);

// 3. Date Only (formatted as string) using JProperty
DateTimeOffset dateOnly = new DateTimeOffset(2023, 10, 26, 0, 0, 0, TimeSpan.Zero);
JProperty dateOnlyProperty = new JProperty("specificDateOnlyOffset", dateOnly.ToString("yyyy-MM-dd"));
jsonObject.Add(dateOnlyProperty);

// 4. Time Only (formatted as string) using JProperty
DateTimeOffset timeOnly = new DateTimeOffset(1, 1, 1, 14, 30, 0, TimeSpan.Zero);
JProperty timeOnlyProperty = new JProperty("specificTimeOnlyOffset", timeOnly.ToString("HH:mm:ss"));
jsonObject.Add(timeOnlyProperty);

// 5. DateTimeOffset with milliseconds using JProperty
DateTimeOffset preciseDateTimeOffset = new DateTimeOffset(2024, 5, 29, 10, 15, 30, 123, TimeSpan.FromHours(5.5));
JProperty preciseDateTimeOffsetProperty = new JProperty("preciseDateTimeOffset", preciseDateTimeOffset);
jsonObject.Add(preciseDateTimeOffsetProperty);

// 6. DateTimeOffset in ISO 8601 format (UTC) using JProperty
DateTimeOffset isoUtcDateTimeOffset = new DateTimeOffset(2025, 1, 15, 8, 0, 0, TimeSpan.Zero);
JProperty isoUtcDateTimeOffsetProperty = new JProperty("isoUtcDateTimeOffset", isoUtcDateTimeOffset.ToString("o", CultureInfo.InvariantCulture));
jsonObject.Add(isoUtcDateTimeOffsetProperty);

// 7. DateTimeOffset in custom format using JProperty
DateTimeOffset customFormattedDateTimeOffset = new DateTimeOffset(2022, 7, 1, 9, 45, 10, TimeSpan.FromHours(-4));
JProperty customFormattedDateTimeOffsetProperty = new JProperty("customFormattedDateTimeOffset", customFormattedDateTimeOffset.ToString("MM/dd/yyyy HH:mm:ss zzz"));
jsonObject.Add(customFormattedDateTimeOffsetProperty);

// 8. Nullable DateTimeOffset (representing a missing or optional date) using JProperty
DateTimeOffset? nullableDateTimeOffset = null;
JProperty nullableDateTimeOffsetProperty = new JProperty("nullableDateTimeOffset", nullableDateTimeOffset);
jsonObject.Add(nullableDateTimeOffsetProperty);

// 9. MinValue DateTimeOffset using JProperty
JProperty minDateTimeOffsetProperty = new JProperty("minDateTimeOffset", DateTimeOffset.MinValue);
jsonObject.Add(minDateTimeOffsetProperty);

// 10. MaxValue DateTimeOffset using JProperty
JProperty maxDateTimeOffsetProperty = new JProperty("maxDateTimeOffset", DateTimeOffset.MaxValue);
jsonObject.Add(maxDateTimeOffsetProperty);

// 11. Exact DateTimeOffset using JProperty
JProperty exactDateTimeOffsetProperty = new JProperty("exactDateTimeOffset", DateTimeOffset.Parse("2025-03-26T20:22:20+02:00"));
jsonObject.Add(exactDateTimeOffsetProperty);

// 12. Various time zone offsets
jsonObject.Add(new JProperty("positiveOffset", new DateTimeOffset(2025, 10, 26, 12, 0, 0, TimeSpan.FromHours(5.5))));
jsonObject.Add(new JProperty("negativeOffset", new DateTimeOffset(2025, 10, 26, 12, 0, 0, TimeSpan.FromHours(-8))));
jsonObject.Add(new JProperty("uncommonOffset", new DateTimeOffset(2025, 10, 26, 12, 0, 0, new TimeSpan(12, 45, 0))));

NewtonsoftInteropTests.VerifyNewtonsoftInterop<JObject>(jsonObject);
}

public enum Day { Sun, Mon, Tue, Wed, Thu, Fri, Sat };

public sealed class ObjectWithAttributes
Expand Down Expand Up @@ -437,4 +505,4 @@ public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectTy
}
}
}
}
}
Loading