0

I have my aplication which uses BST time zone(UTC+1) and another application where i am using the value from the above specified application . On my second server the timezone is UTC. Because of this when i get value in a datetime property there is a diufference of one hour and because of that the value is going wrong. I wont be able to adjust the timezone on both the servers . How can i convert the value to a BST time zone in my second application using .net.

public DateTime? EmploymentStartDate { get; set; }

This is my property in my model.

the value from my first server is 29/8/2001 00:00:00 when it comes to the second server where the timezone is UTC it is 28/9/2001 23:00:00 .

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
coder
  • 23
  • 1
  • 9
  • 3
    store everything as utc. – Daniel A. White Aug 05 '16 at 12:19
  • 2
    *Don't* store everything as UTC, you lose important information and you won't be able to handle times from multiple timezones, ie, multiple countries. Use DateTimeOffset. SQL Server also has a `datetimeoffset` and EF maps the two automatically. If you really care about *timezones* (ie `Europe/London`) instead of just offsets, check NodaTime – Panagiotis Kanavos Aug 05 '16 at 12:24
  • Panagiotis Kanavos :I havent tried DatetimeOffset . DO you have any example – coder Aug 05 '16 at 12:30
  • It's the same as DateTime, only `DateTimeOffset.Now` actually includes your local tz offset. Serialization includes the offset so there is no chance of mixing up offsets. String formatting works the same and you can control whether the offset gets displayed. You can use `ToLocalTimeZone()` or `ToUniversalTime()` to get a converted `DateTime` object if you have to. SQL Server also has a `datetimeoffset` type, so you could write your entire application using only DateTimeOffset – Panagiotis Kanavos Aug 05 '16 at 12:39
  • @PanagiotisKanavos rather than commenting on every other answer, if I were you (and I'm not), I'd post the DateTimeOffset information as an answer. – hometoast Aug 05 '16 at 12:56
  • I tried this varEmploymentStartDate= new DateTime(dt.Ticks, DateTimeKind.Local); But my local system timezone is UTC it is still not getting any difference. I am not sure whether i did right as you said Panag – coder Aug 05 '16 at 13:09
  • EmploymentFromDate.ToLocalTime(); - tried this and it worked . Thans PanagiosKanavos. – coder Aug 05 '16 at 13:37

5 Answers5

0

I agree with Daniel A. White. You should store everything as UTC and convert the date to local date on the client.

Look this https://msdn.microsoft.com/en-us/en-en/library/system.timezoneinfo.converttimefromutc(v=vs.100).aspx

Community
  • 1
  • 1
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • Well if you only work with UTC dates on your sever you don't need to think about time zones at all. Also your client have it more easy if you only return UTC times... Its just something I learned from some senjor developers in my company. Don't you agree? – Martin Brandl Aug 05 '16 at 12:32
  • Also, if you *don't* work with customers from multiple timezones, or you don't care about summer time. That's very restrictive. For example, you couldn't store flight departure times using only UTC as each airport has a different offset – Panagiotis Kanavos Aug 05 '16 at 12:37
  • @PanagiotisKanavos Why? Consider airport A from Timezone 1 books a flight. You receive it on the server and convert it to UTC and store it. If airport B from Timezone 2 retrieves the date and converts it to his local date, he gets the correct date - doesn't he? – Martin Brandl Aug 05 '16 at 12:45
  • In fact, I disagree with your senior devs because I work for an online travel agency and the assumption that you can use UTC for everything is .... unfounded to say the least. It's similar to assuming you can use ANSI instead of Unicode. Never mind supporting web browsers from multiple countries. In any case, even when you *think* you are sending UTC, you are also sending a `Z` or a `+00:00` value that makes the string a value with an offset – Panagiotis Kanavos Aug 05 '16 at 12:46
  • Your airport example is wrong, because flight times are posted and displayed as *local* times with offsets. If we stored only UTC, we'd also have to store the original offset in a separate field, or have to recreate the local time from each airport's timezone data. If you lost your flight because of a wrong offset, we'd rather it was because the *airline* sent the wrong offset so *they* have to refund you, not because we fumbled the unnecessary conversion – Panagiotis Kanavos Aug 05 '16 at 12:48
  • Yes, I know that they are posted as local times but I would just convert them to UTC on the server and save that value. Isn't that right? – Martin Brandl Aug 05 '16 at 12:51
  • The fact is, DateTimeOffset handles timezones. Using anything else *when you have the option* to do so, adds unnecessary complication. – hometoast Aug 05 '16 at 12:54
  • Wrong, as I just said. Because you'd lose the original offset so you wouldn't be able to retrieve a local time. You'd have to either store the offset together with the time, or try to recreate it from the airport's timezone data. You *add* complication by discarding information that is already available – Panagiotis Kanavos Aug 05 '16 at 12:54
  • Be sure that an "absolute" (UTC) value is what's stored, and that when you retrieve something from the database you also get an "absolute" (and, binary) value. If you ask a database to give you the answer as a string, it will probably "helpfully" convert it for you into what it considers to be *its* local time. The application should convert it for display using the user's "locale." – Mike Robinson Aug 05 '16 at 12:55
  • @MikeRobinson indeed, the database has no notion of local/UTC time, unless you *do* use `datetimeoffset` to store the value. Now that SQL Server added the `FORMAT` function we can expect a lot more questions about failed string conversions in SQL – Panagiotis Kanavos Aug 05 '16 at 12:57
  • well. Thanks for that hint, I probably have to think about how I handle dates on the server right now. – Martin Brandl Aug 05 '16 at 12:59
  • The issue to consider is *where* the time is being converted to a printable string. If you ask the *SQL Server* to do it, it will do it *one* way which might be the *wrong* way for wherever your user is. (And it can be complicated: Arizona does not observe daylight savings time *except* on the Navajo Indian Reservation, and so on.) But you can assume ... must assume ... that the user has set the appropriate "locale" time-zone on his own computer. With that, and an absolute (UTC) *binary number,* you can convert the value ... *locally.* – Mike Robinson Aug 05 '16 at 13:07
0

It's simple, you must consider all the DateTime always in UTC, so simply call ToUniversalTime() to convert every instance in UTC timezone:

DateTime dt = DateTime.Now;
dt.ToUniversalTime();
Igor Damiani
  • 1,897
  • 9
  • 12
  • That is the problem here. I cant save the value in UTC on my first server .That is a different application which i am just consuming and i dont have access or any option to change the timezone. – coder Aug 05 '16 at 12:23
  • I am having access only to the second server where timezone is UTC . And here i want to convert the UTC to BST – coder Aug 05 '16 at 12:24
  • Have you checked DateTimeOffset? There is no reason to discard the offset or convert everyting go UTC and lose the initial local time – Panagiotis Kanavos Aug 05 '16 at 12:25
  • Save the DateTime instances in the format that you want (BST on the first server, UTC in the second one), but you need to save also the timezone offset, because in the code you need to reconvert them to a common comparable format. Try to see DateTimeOffset. – Igor Damiani Aug 05 '16 at 12:26
  • @IgorDamiani it's not just comparison - when is the next Olympic award ceremony? Using DateTimeOffset you save one value. With DateTime you have to do two conversion - from BST the brazilian one to BST the British one. Now try displaying this to the browser of a Spanish user – Panagiotis Kanavos Aug 05 '16 at 12:28
0
    private DateTime? _employmentStartDate;
    public DateTime? EmploymentStartDate
    {
        get
        {
            return _employmentStartDate != null ? TimeZoneInfo.ConvertTimeFromUtc(_employmentStartDate.Value, TimeZoneInfo.Local) : new DateTime();
        }
        set
        {
            _employmentStartDate = TimeZoneInfo.ConvertTimeToUtc((DateTime)value);
        }
    }
dm84
  • 3
  • 2
0

Also consult this previous StackOverflow post:

Should MySQL have its timezone set to UTC?

This article (and the numerous other articles and web-pages that it links to) discusses MySQL, but the concerns and techniques are similar for any database and programming language.

Community
  • 1
  • 1
Mike Robinson
  • 8,490
  • 5
  • 28
  • 41
0

While your (the OP's) question seems to be about how to convert time information between time zones, the discussion in the comments has grown hot on the subject of choosing a format for storage. First things first – to convert your UTC time to BST you can use TimeZoneInfo.ConvertTimeFromUtc. This method “converts a Coordinated Universal Time (UTC) to the time in a specified time zone.”

Here’s an example:

var bstZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Daylight Time");
bstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, bstZone);

NB 1: If what you really want is local time on the server when executing, obviously you should rather use ToLocalTime(), and that will yield the same result if that local time happens to be BST (and the Kind property of the DateTime variable is not DateTimeKind.Local).

NB 2: To the best of my knowledge, the TimeZoneInfo class referrers to "British Summer Time" as "GMT Daylight Time", and I’m assuming that’s what you refer to as BST. But don’t take my word for it – you need to make sure yourself that you have the right time zone ID.

Now, about storing:

TL;DR

A time signature without time zone information is unreliable information. Given this premise, there is however no true “right or wrong” time zone to use for storing. While most people might argue that UTC is to be considered a best practice, first of all that information (that it's in UTC) should still be stored explicitly alongside the timestamp, and secondly, there may be practical reasons why another format is preferable in a specific scenario.

When performing arithmetic calculations on time values you should use universal time representations to avoid hiccups with regard to daylight saving practices and such.

Be weary of complications that might arise from serializing and de-serializing mechanisms making the wrong assumptions about the information you provide, e.g. System.XML.Serialization or a database engine.

Obviously, when presenting your time information (that is, when creating a string representation suitable for interpretation by humans), you should do so in whatever format the user should be expecting. Regardless of how you persist your values, conversions (with offset) may be necessary to do so.

Check out these links for more information:

Oskar Lindberg
  • 2,255
  • 2
  • 16
  • 36