Skip to content

Commit

Permalink
Fix timezone deserialization with non-system timezones in Device cont…
Browse files Browse the repository at this point in the history
…ext (#993)

* Fix timezone deserialization with non-system timezones in Device context

* tdd lol

* changelog
  • Loading branch information
Tyrrrz authored May 12, 2021
1 parent b14d5fc commit 4016f2b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Default environment to "debug" if running with debugger attached (#978)

### Fixes

- Fixed an issue where an attempt to deserialize `Device` with a non-system time zone failed (#993)

## 3.3.4

### Features
Expand Down
22 changes: 21 additions & 1 deletion src/Sentry/Protocol/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public sealed class Device : IJsonSerializable
/// </summary>
public const string Type = "device";

// TODO: remove this and replace with separate properties for 'timezone' and 'timezone_display_name'
// since we don't carry enough data to deterministically recreate a TimeZoneInfo instance.
/// <summary>
/// The timezone of the device.
/// </summary>
Expand Down Expand Up @@ -333,12 +335,30 @@ public void WriteTo(Utf8JsonWriter writer)
writer.WriteEndObject();
}

private static TimeZoneInfo? TryParseTimezone(JsonElement json)
{
var timezoneId = json.GetPropertyOrNull("timezone")?.GetString();
var timezoneName = json.GetPropertyOrNull("timezone_display_name")?.GetString() ?? timezoneId;

if (string.IsNullOrWhiteSpace(timezoneId))
return null;

try
{
return TimeZoneInfo.FindSystemTimeZoneById(timezoneId);
}
catch (TimeZoneNotFoundException)
{
return TimeZoneInfo.CreateCustomTimeZone(timezoneId, TimeSpan.Zero, timezoneName, timezoneName);
}
}

/// <summary>
/// Parses from JSON.
/// </summary>
public static Device FromJson(JsonElement json)
{
var timezone = json.GetPropertyOrNull("timezone")?.GetString()?.Pipe(TimeZoneInfo.FindSystemTimeZoneById);
var timezone = TryParseTimezone(json);
var name = json.GetPropertyOrNull("name")?.GetString();
var manufacturer = json.GetPropertyOrNull("manufacturer")?.GetString();
var brand = json.GetPropertyOrNull("brand")?.GetString();
Expand Down
17 changes: 17 additions & 0 deletions test/Sentry.Tests/Protocol/Context/DeviceTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using Sentry.Internal;
using Sentry.Tests.Helpers;
using Xunit;

Expand Down Expand Up @@ -158,6 +160,21 @@ public void SerializeObject_TestCase_SerializesAsExpected((Device device, string
Assert.Equal(@case.serialized, actual);
}

[Fact]
public void FromJson_NonSystemTimeZone_NoException()
{
// Arrange
const string json = "{\"type\":\"device\",\"timezone\":\"tz_id\",\"timezone_display_name\":\"tz_name\"}";

// Act
var device = Device.FromJson(Json.Parse(json));

// Assert
device.Timezone.Should().NotBeNull();
device.Timezone?.Id.Should().Be("tz_id");
device.Timezone?.DisplayName.Should().Be("tz_name");
}

public static IEnumerable<object[]> TestCases()
{
yield return new object[] { (new Device(), "{\"type\":\"device\"}") };
Expand Down

0 comments on commit 4016f2b

Please sign in to comment.