KIC
KIC

Reputation: 6121

Changing Timezone of DateTime to satisfy API contract

I have a swagger generated client. Surprisingly the API expects all date parameters to be exactly in UTC+02:00 and cant handle just the time zone information provided. Now whatever I do, I can't get the timezone bit correct (+02:00). The following code always prints +01:00 regardless of the time zone I provide.

TimeZoneInfo.ConvertTime(new DateTime(2020, 1, 8, 0, 0, 0, DateTimeKind.Utc), TimeZoneInfo.FindSystemTimeZoneById("Asia/Magadan")).ToString("zzz")

As I mentioned earlier this is a generated client over which I have no control. So I can not mess with the json serializer. API:

List<GLJournalEntry> Create (PostGLJournalEntriesDTO body, string idempotencyKey = null);

DTO:

        public PostGLJournalEntriesDTO(List<GLAccountAmount> credits = default(List<GLAccountAmount>), List<GLAccountAmount> debits = default(List<GLAccountAmount>), string branchId = default(string), DateTime? date = default(DateTime?), string notes = default(string), string transactionId = default(string))
        {
            this.Credits = credits;
            this.Debits = debits;
            this.BranchId = branchId;
            this.Date = date;
            this.Notes = notes;
            this.TransactionId = transactionId;
        }

JSON-Model:

"PostGLJournalEntriesDTO":{
         "type":"object",
         "properties":{
              "date":{
               "type":"string",
               "format":"date-time",
               "example":"2016-09-06T13:37:50+03:00",
               "description":"Date/time stamp when the entries were recorded (Booking Date)"
            
},
            "branchId":{
               "type":"string",
               "description":"The id of the assigned branch for the journal entries"
            
},
            "notes":{
               "type":"string",
               "description":"Optional notes entered by the user when they performed the journal entry log"
            
},
            "credits":{               "type":"array",
               "description":"The list of GL Accounts to be credited with the corresponding amounts",
               "items":{
                  "$ref":"#/definitions/GLAccountAmount"
               
}
            
},
            "debits":{               "type":"array",
               "description":"The list of GL Accounts to be debited with the corresponding amounts",
               "items":{
                  "$ref":"#/definitions/GLAccountAmount"
               
}
            
},
            "transactionId":{
               "type":"string",
               "description":"An id for the transaction. Not unique. Will be auto generated if not provided."
            
}
         
},
         "description":"The representation of a payload for creating GL Journal Entries"
      
}

An id for the transaction. Not unique. Will be auto generated if not provided. }

When I invoke the API I get an exception:

{"errors":[{"errorCode":4,"errorSource":"Invalid date offset for value 2020-01-08T23:00:00+01:00 of date org offset is +02:00","errorReason":"INVALID_PARAMETERS"}]}

If I curl the api using 2020-01-08T23:00:00+02:00, everything works.

It is pretty clear that this is a bug on their end (as even the example states a date with +03:00). However I cant wait for them fixing this for me and I need to find a workaround (at least an intermediate one). The generated client uses RestSharp to serialize out the json (Newtonsoft.Json.JsonConvert).

Upvotes: 3

Views: 2338

Answers (1)

sunside
sunside

Reputation: 8249

Avoid DateTime whenever possible and use DateTimeOffset instead:

var sourceOffset = TimeSpan.Zero; // UTC
var source = new DateTimeOffset(2020, 1, 8, 0, 0, 0, sourceOffset);

The rest of your code doesn't change:

var timezone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Magadan");
var timezoneStr = TimeZoneInfo.ConvertTime(source, timezone).ToString("zzz");

This will give +11:00 (which is correct for Magadan Time). If you need to convert from Magadan Time to UTC+2, you'd need to change the offset and target time zones accordingly.


As an example, here's how to go to UTC+2 as currently observed by the Africa/Cairo time zone:

var utcPlus2 = TimeZoneInfo.FindSystemTimeZoneById("Africa/Cairo");
var converted = TimeZoneInfo.ConvertTime(target, utcPlus2);
var dateTime = converted.DateTime;

Now, the dateTime value will be 1/8/2020 2:00:00 AM - which is correct, since 1/8/2020 0:00:00 AM UTC is 1/8/2020 2:00:00 AM UTC+2. Note that while you will not be able to get the correct time zone from the DateTime instance, the time value itself is correct.

Upvotes: 3

Related Questions