WooCommerce.NET icon indicating copy to clipboard operation
WooCommerce.NET copied to clipboard

Please specify DateTimeKind of GMT datetimes as UTC

Open gaazkam opened this issue 4 years ago • 1 comments

Make sure you have included the below details when open an issue. Thank you.

  • Wordpress version, WooCommerce version and WooCommerce.NET version

WP is 5.7.2, Woo is 5.4.1, WC.NET is 0.8.3

  • Steps to replicate the issue

Run the following code:

static async Task Main(string[] args)
{
    var wc = new WCObject(new RestAPI
    (
        "redacted",
        "redacted",
        "redacted"
        requestFilter: request =>
        {
            request.UserAgent = "TestTZ";
            request.Accept = "application/json";
        }
    ));

    var order = await wc.Order.Get(192);
    Console.WriteLine(order.date_created_gmt.Value.Kind);

    Console.ReadLine();
}

It prints out Unspecified.

In my opinion date_created_gmt should have its kind specified as DateTimeKind.UTC, because it is an UTC DateTime.

This can be a source of hard to find bugs. For example, depending on the timezone, the following code might not give expected results:

var order = await wc.Order.Get(193);
var after = order.date_created_gmt.Value;
var ordersAfter193 = await wc.Order.GetAll(new Dictionary<string, string> {{"after", after.ToString("o")}});

This code, however, will give expected results:

var order = await wc.Order.Get(193);
var after = DateTime.SpecifyKind(order.date_created_gmt.Value, DateTimeKind.UTC);
var ordersAfter193 = await wc.Order.GetAll(new Dictionary<string, string> {{"after", after.ToString("o")}});

I've already made this mistake twice :(

gaazkam avatar Jun 25 '21 19:06 gaazkam

The code doesn't have any logic around these fields - it relies on the JSON deserialization to get the data.

This is arguably a shortcoming of the data coming from WordPress and/or WooCommerce.

Fixing it will require changing every instance of DateTime? date_[Something]_gmt {get; set;} with something like:

        /// <summary>
        /// The date the webhook delivery was logged, GMT.   
        /// </summary>
        [DataMember(EmitDefaultValue = false)]
        public DateTime? date_created_gmt
        {
            get => date_Created_Gmt;
            set
            {
                date_Created_Gmt = value.HasValue ? (DateTime?)DateTime.SpecifyKind(value.Value, DateTimeKind.Utc) : value;
            }
        }
        DateTime? date_Created_Gmt;

while not difficult, there are many instances. Which makes it 'not quite' trivial.

pricerc avatar Jul 22 '21 10:07 pricerc