Get Spain time in C# - c#

I need to get Spanish time in an Azure Function. I have used this code in C#:
DateTime date = DateTime.UtcNow;
It give me an incorrect datetime and I don't know how I can the correct datetime.
For example, if I use the code above at 20:30 in Spanish time, I will get 18:30 in utc.
Can anyone help me?

You need to use DateTimeOffset type instead of DateTime
// First get the TimeZone by ID. Spain Timezone is "Romance Standard Time"
var tz = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");
// This would return +1 in winter and +2 in summer when daylight saving is active
var offset = tz.GetUtcOffset(DateTime.UtcNow);
// Get Time based on the current offset (+1 in winter +2 in summer)
var now = DateTimeOffset.UtcNow.ToOffset(offset);
Update for Azure since apparently TimezoneInfo is not present in the machine registry
// Timezones are usually stored in windows registry. Since apparently it is not stored on Azure, we can recreate the TimeZoneInfo object manually
// This is the Spanish Timezone based on current Ppanish law.
var tz = TimeZoneInfo.CreateCustomTimeZone(
id: "Romance Standard Time",
baseUtcOffset: TimeSpan.FromHours(1),
displayName: "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris",
standardDisplayName: "Romance Standard Time",
daylightDisplayName: "Romance Daylight Time",
adjustmentRules: new[] {
TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
dateStart: DateTime.MinValue,
dateEnd: DateTime.MaxValue,
daylightDelta: TimeSpan.FromHours(1),
daylightTransitionStart: TimeZoneInfo.TransitionTime.CreateFloatingDateRule(
timeOfDay: new DateTime(1, 1, 1, 2, 0, 0, DateTimeKind.Unspecified), // Starts at 2AM
month: 3, // Daylight starts on March
week: 5, // Last week of the month
dayOfWeek: DayOfWeek.Sunday), // Starts on Sunday
daylightTransitionEnd: TimeZoneInfo.TransitionTime.CreateFloatingDateRule(
timeOfDay: new DateTime(1, 1, 1, 3, 0, 0, DateTimeKind.Unspecified), // Ends at 3AM
month: 10, // Daylight ends in October
week: 5, // Last week of October
dayOfWeek: DayOfWeek.Sunday) // Ends On Sunday
)
});
// This would return +1 in winter and +2 in summer when daylight saving is active
var offset = tz.GetUtcOffset(DateTime.UtcNow);
// Get Time based on the current offset (+1 in winter +2 in summer)
var now = DateTimeOffset.UtcNow.ToOffset(offset);
An important note though, .NET class library takes in consideration only the current laws regarding daylight saving and timezone. If you want to take into consideration historical changes use Noda Time Library

You will need to convert the UTC time running in Azure Functions into the time zone you require, similar to this:
TimeZoneInfo.ConvertTimeFromUtc(
DateTime.UtcNow,
TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");

UTC is Universal Time
you can use
DateTime.Now()
for show local time

Related

Getting the Arizona Standard Time in .net

I have an application in which time zones are treated as string, by using the system name so we can make an actual System.TimeZoneInfo object by doing:
var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
Such values are persisted to DB, now we are facing an issue where one such object is requested to be on Arizona Time which is not a standard timezone. From what I have investigated the Arizona Time changes Time Zones due to the fact that it doesn't observes "Day Light Savings".
I am looking for a way to set one value in DB so that there is no need to change it according to day light savings changes.
Is there a way to do this?
Even if I have to change a bit the code to get the TimeZoneInfo object. What really matters to me is a way to determine the actual timezone corresponding to Arizona Time
About Arizona time zones
From timeanddate.com:
There is a common misconception that Arizona is on Pacific Daylight
Time (PDT) during the summer and on Mountain Standard Time (MST)
during the winter. Because MST and PDT have the same UTC offset of
minus 7 hours (UTC-7), Arizona has the same local time as neighboring
states California and Nevada during the summer season. Although the
time is the same, Arizona uses standard time (MST) all year.
“Daylight” time zones, such as MDT, are mostly used for areas that
switch to DST every year
IANA (tz database) time zone database contains two time zones for Arizona:
America/Phoenix (Mountain Standard Time - Arizona, except Navajo), which does not observe daylight saving changes (DST), and
America/Shiprock, which observes DST.
Arizona time zones in .NET
Depending on your users' exact location in Arizona, you should use either America/Phoenix or America/Shiprock time zone, so you will need two values in the database. However, if you try to get time zones with TimeZoneInfo.FindSystemTimeZoneById using tz database names, you will get System.TimeZoneNotFoundException.
In order to get Arizona time zone that does not observe DST (America/Phoenix), you can use:
TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time")
In order to get Arizona time zone that does observe DST (America/Shiprock), you can use:
TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time")
So, you would have both ids in your database, US Mountain Standard Time and Mountain Standard Time, or alternatively some other strings that you would later map to these .NET time zone ids.
Check out NodaTime, it can help you a lot when it comes to dealing with date, time and time zones.
And finally, here is a sample program (with NodaTime) that demonstrates the difference between .NET US Mountain Standard Time (America/Phoenix, Arizona without DST) and Mountain Standard Time (America/Shiprock, Arizona with DST).
using System;
using NodaTime;
using NodaTime.TimeZones;
namespace TimeZoneExample
{
class Program
{
static void Main(string[] args)
{
// Arizona without daylight saving time (TZ: America/Phoenix)
var mstWithoutDstTz = TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time");
// Arizona with daylight saving time (TZ: America/Shiprock)
var mstWithDstTz = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
// NodaTime BclDateTimeZone for Arizona without daylight saving time
var mstWithoutDstNodaTz = BclDateTimeZone.FromTimeZoneInfo(mstWithoutDstTz);
// NodaTime BclDateTimeZone for Arizona with daylight saving time
var mstWithDstNodaTz = BclDateTimeZone.FromTimeZoneInfo(mstWithDstTz);
// January 1, 2017, 15:00, local winter date
var localWinterDate = new LocalDateTime(2017, 01, 01, 15, 00);
// NodaTime ZonedDateTime for Arizona without daylight saving time: January 1, 2017, 15:00
var winterTimeWithoutDst = mstWithoutDstNodaTz.AtStrictly(localWinterDate);
// NodaTime ZonedDateTime for Arizona with daylight saving time: January 1, 2017, 15:00
var winterTimeWithDst = mstWithDstNodaTz.AtStrictly(localWinterDate);
// Both time zones have the same time during winter
Console.WriteLine($"Winter w/o DST: {winterTimeWithoutDst}"); // 2017-01-01T15:00:00 US Mountain Standard Time (-07)
Console.WriteLine($"Winter w/ DST: {winterTimeWithDst}"); // 2017-01-01T15:00:00 Mountain Standard Time (-07)
// add 180 days to get June 30, 2017
var sixMonthsToSummer = Duration.FromTimeSpan(new TimeSpan(180, 0, 0, 0));
// During summer, e.g. on June 30, Arizona without daylight saving time is 1 hour behind.
Console.WriteLine($"Summer w/o DST: {winterTimeWithoutDst + sixMonthsToSummer}"); // 2017-06-30T15:00:00 US Mountain Standard Time (-07)
Console.WriteLine($"Summer w/ DST: {winterTimeWithDst + sixMonthsToSummer}"); // 2017-06-30T16:00:00 Mountain Standard Time (-06)
}
}
}
If I understand your problem correctly, you want to create a custom time zone representing "Arizona Time" which has a constant offset from UTC regardless the date of the year.
If so, you should be able to use the static method
TimeZoneInfo.CreateCustomTimeZone
Just set the TimeSpan to the number of hours from UTC that you need it to be (-7 hours from what I can tell).
https://msdn.microsoft.com/en-us/library/bb309898(v=vs.110).aspx
EDIT: You might also have some success by simply using the named timezone
"US Mountain Standard Time"
which should represent the same.

TimeZoneInfo.ConvertTime from PST to UTC to AEST - off by one hour

I convert a string that represents a time in Pacific Time Zone that I am using to create a DateTime object:
var pacificDateTime = new DateTime(2016, 11, 16, 15, 0, 0) // 11/16/2016 3:00:00 PM
Using that, I create a DateTimeOffset because ultimately it becomes a bit easier to work with.
var pacificTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var dateTimeNoKind = new DateTime(pacificDateTime.Ticks, DateTimeKind.Unspecified)
var DateTimeOffsetValue = TimeZoneInfo.ConverTimeToUtc(dateTimeNoKind, pacificTimeZoneInfo) // 11/16/2016 11:00:00 PM
So far so good. The difference between UTC and Pacific is that UTC is ahead by 8 hours (the given time is within daylight savings).
Then I want to convert from UTC to AEST—but this is where the problem appears:
var australianEasternTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
TimeZoneInfo.ConvertTime(DateTimeOffsetValue, australianEasternTimeZoneInfo) // 11/17/2016 10:00:00 AM
AEST is ahead of UTC by 10 hours. I had expected the value to be 11/17/2016 09:00:00 AM but instead I am getting an extra hour added to my result.
As a test, when I convert to PST or GMT or EST from the UTC time, they appear to convert back correctly.
I feel like I am missing something obvious or overlooking something simple?
From Wikipedia's Time in Australia article:
Australia has two eastern time zones. In the northeast, UTC+10 applies all year. In the southeast, UTC+10 applies during standard time, and UTC+11 applies during daylight time (aka summer time).
The northeast region (Queensland) uses the IANA time zone identifier "Australia/Brisbane", while the southeast region (New South Wales) uses "Australia/Sydney". These correspond to the Windows time zone identifiers: "E. Australia Standard Time" and "AUS Eastern Standard Time" respectively.
If you are converting for Queensland, use "E. Australia Standard Time".
If you are converting for New South Wales, use "AUS Eastern Standard Time".
As to the confusing nature of these identifiers, see the section about Windows time zones in the timezone tag wiki.
If you want to use the standard IANA identifiers instead, use Noda Time.

ConvertTimeToUtc is always off by one hour

I am facing issue while converting datetime to UTC.
User enters date in mydate in the webform, which we need to convert in UTC and store it in DB.
User also selects timezone from the list which is stored in selectedTimeZone variable. So we have to convert mydate from selectedTimeZone to UTC.
TimeZoneInfo.ConvertTimeToUtc(mydate, selectedTimeZone);
Example#1 :
If mydate = 05/02/2016 09:00 AM and selectedTimeZone = EST (-5:00) then
TimeZoneInfo.ConvertTimeToUtc(mydate, selectedTimeZone) returns
05/02/2016 13:00
which is off by one hour
Example#2
If mydate = 05/02/2016 09:00 AM and selectedTimeZone = IST (indian
standard time) (+5:30) then TimeZoneInfo.ConvertTimeToUtc(mydate,
selectedTimeZone) returns 05/02/2016 03:30
which is correct
There are multiple examples like this.
What is the issue?
Edit:
I don't need to convert user input to DateTime as .net does it, we are getting mydate in mvc action method parameter.
I tried it by setting local timezone of a machine to UTC, London, IST..... but it makes no difference to the output.
It seems adjustment rules for given timezone play their role here. Take the following code:
var mydate = new DateTime(2016, 05, 02, 9, 0, 0);
var selectedTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var dstRule = selectedTimeZone.GetAdjustmentRules().FirstOrDefault(c => c.DateStart < mydate && c.DateEnd > mydate);
There is just one adjustment rule for EST timezone which is active at given time (it is active starting at 2007 year), and this rule works from second Sunday of March to first Sunday of November every year, adjusting time by one hour during that period. That is why you observe that behaviour. If you try to convert date outside of period for this rule (say, in February) - you will get what you would expect.
So to clarify: EST timezone has base offset of UTC-5, but because of daylight savings becomes UTC-4 during summer, and because your time is "summer" - .NET actually correctly converts that to UTC, it's not "off by one hour".

Incorrect time using TimeZoneInfo.ConvertTime()

I'm getting an unexpected DateTime when converting from:
(UTC) Dublin, Edinburgh, Lisbon, London to (UTC-08:00) Baja California
Below is the code I have been using. I'm expecting serverDateTime to be 29/03/2016 00:00:01 (-8 hours), but instead I get 28/03/2016 23:00:01 - which is a 9 hour difference.
private static void Main(string[] args)
{
ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
TimeZoneInfo localTimeZone = timeZones.FirstOrDefault(tz => tz.DisplayName.Contains("London"));
TimeZoneInfo serverTimeZone = timeZones.FirstOrDefault(tz => tz.DisplayName.Contains("California"));
DateTime clientDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 29, 8, 0, 1);
DateTime serverDateTime = TimeZoneInfo.ConvertTime(clientDateTime, localTimeZone, serverTimeZone);
}
My local machine is in the UK, which is currently UTC+1, and Baja - California is currently UTC-7, so I'm expecting to get an 8 hour difference, instead of 9. What am I doing wrong?
Thanks in advance.
A few things:
"(UTC-08:00) Baja California" refers to Baja California, Mexico - not California, USA.
This zone entry follows Mexican DST rules, which doesn't start DST until April 3rd this year. Thus this entry is on UTC-8 still, explaining the time difference you observed.
This particular entry is actually wrong in Windows, as it turns out that the entire state of Baja California follows USA rules for daylight saving time, not Mexican rules.
There is an extensive multi-thread discussion of this in the tz mailing list archives in October and November 2015. This resulted in the corresponding IANA zone America/Santa_Isabel being deprecated with release 2016a. It now links to America/Tijuana instead, which already had been following USA DST rules.
Microsoft has not yet made a similar change to its data, but it is likely in a future update to the Windows time zone data. (I have already communicated this to the appropriate personnel.) In the meantime, use "(UTC-08:00) Pacific Time (US & Canada)" - even if you're talking about Baja California, Mexico.
Don't try to look up a time zone by its DisplayName. Those values will be different depending on operating system language. Instead, use TimeZoneInfo.FindSystemTimeZoneById. The Id properties are not localized. Additionally, Microsoft considers the Id values to be stable identifiers, and thus they will not change with future updates. The DisplayName values have been modified in the past, and could indeed change in the future.
Use the ID "GMT Standard Time" for "(UTC) Dublin, Edinburgh, Lisbon, London"
Use the ID "Pacific Standard Time" for "(UTC-08:00) Pacific Time (US & Canada)"
The ID "Pacific Standard Time (Mexico)" is for "(UTC-08:00) Baja California" - but for the reasons I described, don't use this entry.
Really, you shouldn't be concerned with the time zone on the server at all. The server should only be concerned with UTC. (note that London is not UTC, since it switches for BST in the summer)
I'm not sure what you're intention was with this line:
DateTime clientDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 29, 8, 0, 1);
Pulling the month and year from DateTime.Now is going to use the server's time zone. Then you combine with fixed day of 29 and fixed time at 8:00:01. This will fail in February of a non-leap year (when there are only 28 days in the month), and also could give bad dates when the server's date is not in the same month and year as the client's (such as near the transition from one month to another).

Example of ambiguous DateTimeOffset

We have DateTimeOffsets in Database/Model. To display these values in Web, we convert the DateTimeOffsets into the current user's timezone.
According MSDN, DateTimeOffset can be ambiguous in a specific TimeZone:
TimeZoneInfo.IsAmbiguousTime Method (DateTimeOffset)
This doesn't make sense to me at all. Can someone please give me an example DateTimeOffset which is ambiguous?
We're in TimeZone "W. Europe Standard Time".
Does what the documentation says not make it clear?
Typically, ambiguous times result when the clock is set to return to standard time from daylight saving time
I.e. if at 2am you come off of DST and reset the clock to 1am, then if someone starts talking about 1.30am, you don't know if that's 30 minutes from now or happened 30 minutes in the past.
There are a set of values (typically an hour long) which map to two different set of moments in UTC time.
I think the confusion comes from the way that "ambiguous" is defined here.
To be clear, a DateTimeOffset is never ambiguous unto itself. It always represents a specific moment in absolute, instantaneous time. Given a date, time, and offset, I can tell you both the local wall-time, and the precise UTC time (by applying the offset).
However, the wall-time portion of the value can be ambiguous within a specific time zone. That is, the date and time only when you ignore the offset. That's what TimeZoneInfo.IsAmbiguousTime is telling you. That if it weren't for the offset, the value would be ambiguous. The wall-time may be one that a person in that time zone might find confusing.
Consider that there are two overloads of this method, one that takes a DateTime and one that takes a DateTimeOffset.
The DateTime one makes perfect sense when .Kind is DateTimeKind.Unspecified.
DateTime dt = new DateTime(2016, 10, 30, 2, 0, 0);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dt); // true
It makes a little less sense with the other kinds, because it does conversions to the given time zone first - but still it does the same thing:
DateTime dt = new DateTime(2016, 10, 30, 1, 0, 0, DateTimeKind.Utc);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dt); // true
The DateTimeOffset overload is essentially doing the same thing as the previous example. Whatever the offset is, it gets applied to the date and time, then ambiguity is checked on the resulting date and time alone - just like in the first example.
DateTimeOffset dto = new DateTimeOffset(2016, 10, 30, 2, 0, 0, TimeSpan.FromHours(1));
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dto); // true
Even with an offset that is meaningless to that time zone, it still gets applied before comparing.
DateTimeOffset dto = new DateTimeOffset(2016, 10, 29, 19, 0, 0, TimeSpan.FromHours(-5));
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dto); // true
It boils down to the implementation of the overload, which is essentially:
// Make sure the dto is adjusted to the tz. This could be a no-op if it already is.
DateTimeOffset adjusted = TimeZoneInfo.ConvertTime(dto, tz);
// Then just get the wall time, stripping away the offset.
// The resulting datetime has unspecified kind.
DateTime dt = adjusted.DateTime;
// Finally, call the datetime version of the function
bool ambiguous = tz.IsAmbiguousTime(dt);
You can see this in the .net reference source here. They condense it to two lines, and preface it with a shortcut for better perf when DST is not applicable, but that's what it does.
Well the sample is (the last October's Sunday 2:00-3:00)
DateTimeOffset example = new DateTimeOffset(2015, 10, 25, 2, 30, 0,
new TimeSpan(0, 2, 0, 0));
TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
if (tst.IsAmbiguousTime(example))
Console.Write("Ambiguous time");
Opposite to Ambiguous time is Invalid time (the last March's Sunday 2:00-3:00):
TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
if (tst.IsInvalidTime(new DateTime(2016, 03, 27, 2, 30, 0)))
Console.Write("Invalid time");

Categories

Resources