2

DateTime type has an enum property called 'DateTimeKind', which can be set as one of these: 'Local', 'Unspecified' and 'Utc'.

When the value gets queried from database with 'datetime' format, if it is being queried using Dapper, this DateTimeKind is 'Unspecified' and then automatically calculate the time to local time as being instantiated inside 'DateTimeOffset' object.

Current back-end standard is Utc and I would like to create a property handling this 'DateTimeKind' value default to 'Utc' as that is what to be expected.

And not only that, I would like to create some helper function auto-convert datetime value as well as setting specifyKind to 'Utc' if it was fed as different kind.

One simple thought into it is handling in setter something like:

    private DateTime? _someValue;
    [DataMember]
    public DateTime? SomeValue
    {
        get
        {
            return _someValue;
        }
        set
        {
            if (value.HasValue)
            {
                 //Todo: do something more such as converting datetime value as well if DateTimeKind was not Utc as coming in..
                _someValue = DateTime.SpecifyKind(value.Value, DateTimeKind.Utc);
            }
        }
    }

Please let me know if there is known way not to reinvent wheels.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
swcraft
  • 2,014
  • 3
  • 22
  • 43
  • Could you clarify what you mean by "and then automatically calculate the time to local time as being instantiated inside DateTimeOffset object"? It's unclear what you're trying to achieve - including what you mean by "create some helper function auto-convert datetime value". If you want to keep the current date/time value but *just* change the Kind to UTC, then you're already doing the right thing... and if your database is storing UTC, it sounds like that *is* what you want to do. – Jon Skeet Nov 14 '19 at 19:12
  • @swcraft - I'm closing as duplicate with regard to Dapper. See [that answer](https://stackoverflow.com/a/39730278/634824) for how to tell Dapper that you want all `DateTime` values to be set with `DateTimeKind.Utc`. If your question is more generalized than that, please let me know. – Matt Johnson-Pint Nov 14 '19 at 19:24
  • @JonSkeet - if the datetime value was coming as DateTime.Kind = 'Local', then I want to convert it to Utc time with DateTime.Kind = 'Utc'. I edited the answer below to be more precise handling different scenarios. thanks. – swcraft Nov 14 '19 at 19:30
  • @swcraft: So you want to perform a time zone conversion in *that* case, but not when it's got a kind of Unspecified, presumably? I suspect you'll want to write a method for that. – Jon Skeet Nov 14 '19 at 19:35
  • @JonSkeet - you are right, and I ended up wrting an extension method of DateTime. – swcraft Nov 14 '19 at 19:40

2 Answers2

3

You could use DateTime.ToUniversalTime() in setter:

    private DateTime? _someValue;
    [DataMember]
    public DateTime? SomeValue
    {
        get
        {
            return _someValue;
        }
        set
        {
            if (value.HasValue)
            {
                if(value.Kind == DateTimeKind.Local)
                {
                   _someValue = value.Value.ToUniversalTime();
                }
                else if(value.Kind == DateTimeKind.Unspecified)
                {
                   _someValue = DateTime.SpecifyKind(value, DateTimeKind.Utc)
                }
            }
        }
    }
swcraft
  • 2,014
  • 3
  • 22
  • 43
hal
  • 1,705
  • 1
  • 22
  • 28
  • 1
    Does this auto-set the Kind to Utc? – swcraft Nov 12 '19 at 18:20
  • 1
    It will force to use DateTImeKind.Utc in returned DateTime. – hal Nov 12 '19 at 18:22
  • 1
    Note that if value's DateTimeKind is Unspecified, it will be considered as universal time without changes in time zone. – hal Nov 12 '19 at 18:23
  • 2
    @hal: No, it will be considered as *local*, and undergo time zone conversion. From the remarks in the doc you linked to: "Unspecified The current DateTime object is assumed to be a local time, and the conversion is performed as if Kind were Local." That's not what the OP wants to do, if I've understood them correctly (although it's not terribly clear) – Jon Skeet Nov 14 '19 at 19:10
  • 2
    @swcraft: You've currently accepted this answer - I'd strongly advise you to check that you really do want to perform a local -> UTC *conversion*. – Jon Skeet Nov 14 '19 at 19:13
  • Good point @JonSkeet.. hal, allow me to edit your answer to be fully functioning without any misleading. – swcraft Nov 14 '19 at 19:22
1

DateTime is immutable struct, you cannot modify anything.

You have to set the DateTimeKind when creating the struct, Some of the many constructors include the DateTimeKind.

The default is DateTimeKind.unspecified, that's conclusive, cause you haven't specified it.

You can just do this, if you want it explicit.

  DateTime time2 = new DateTime(time1.Ticks, DateTimeKind.Utc) 

That is a cheap operation, cause it's a struct. It's not really allocating memory on the heap here.

Holger
  • 2,446
  • 1
  • 14
  • 13
  • 1
    I think using DateTime.SpecifyKind is a clearer way of doing this. – Jon Skeet Nov 14 '19 at 19:11
  • Yes, matter of taste, one is as good as the other. Wanted to point out what's going on, and that this Setting has nothing to do with conversions, it's more an additional information. – Holger Nov 14 '19 at 23:17