Generating DateTime to XML with specific timezone - c#

I want to generate the following DateTime format to XML:
2017-11-12T01:00:00-06:00
I am in the Eastern Standard Time zone which is -5 so when I do:
DateTime operatingDayLocal = DateTime.SpecifyKind(currentDate, DateTimeKind.Local);
the result is:
2017-11-12T01:00:00-05:00
I have to use the same DateTime format which is T00:00:00-00:00 but keeping the same time. I only want to change the offset of the DateTime so it can be generated to XML properly.
I tried this, but the time changes and the offset is gone:
DateTime operatingDayCentralTime = TimeZoneInfo.ConvertTime(currentDate, TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"));
Which results to : 2017-11-12T00:00:00

Related

Is there a way to group by a range of dates or datetimeoffset?

I have a bunch of data with a DateTime that's in UTC, I want to group each data by date by using .GroupBy, but I want to group them according to CST or EST. Is there a way to do this using EF core? I haven't been successful at finding if this is possible by using DateTimeOffset or TimeSpan.
You can create a TimeZoneInfo object representing e.g. Eastern Standard Time with the TimeZoneInfo.FindSystemTimeZoneById method. (Note: this depends on the OS timezone rules, which e.g. in the case of Windows do not cover all DST history.)
var tzest = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
Then you can convert any given DateTime test that has DateTime.Kind of DateTimeKind.Utc to the new timezone:
var testest = TimeZoneInfo.ConvertTime(test, tzest);
If your DateTime has Kind as Unspecified you can use TimeZoneInfo.ConvertTimeFromUtc():
var testest = TimeZoneInfo.ConvertTimeFromUtc(test, tzest);
If test has TimeZoneKind.Local, this will throw an exception and you will need to override the TimeZoneKind:
var testest = TimeZoneInfo.ConvertTimeFromUtc(DateTime.SpecifyKind(test, DateTimeKind.Utc), tzest);

ASP.NET MVC convert DateTime to UTC to send to API

I need to send a start date and end date to an API in UTC format, I have tried the following:
DateTime startDate = Convert.ToDateTime(start + "T00:00:00Z").ToUniversalTime();
DateTime endDate = Convert.ToDateTime(end + "T23:59:59Z").ToUniversalTime();
But it appears they are not converting to UTC, what would be the proper way to take startDate and endDate and convert them over to UTC?
start is a string and is 2018-08-31 and end date is also a string and is 2018-08-31 I added the times in the code above to cover the full date.
Assuming you want endDate to represent the last possible moment on the given date in UTC:
DateTime startDate = DateTime.ParseExact(start, "yyyy-MM-dd", CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
DateTime endDate = DateTime.ParseExact(end, "yyyy-MM-dd", CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
.AddDays(1).AddTicks(-1);
A few other things:
ToUniversalTime converts to UTC from the computer's local time zone (unless .Kind == DateTimeKind.Utc). You should generally avoid it unless the computer's local time zone is relevant to your situation.
In the above code, you need both AssumeUniversal to indicate that the input date is meant to be interpreted as UTC, and AdjustToUniversal to indicate that you want the output value to be kept in terms of UTC and not the computer's local time zone.
UTC is not a "format". Your combined date and time strings would be in ISO 8601 extended format (also RFC 3339 compliant).
Generally, try not to use Convert.ToDateTime. It is equivalent to DateTime.Parse with CultureInfo.CurrentCulture and no DateTimeStyles. That may work for some scenarios, but it is usually better to be more specific.
.AddDays(1).AddTicks(-1) is there to get you to the last representable tick on that date. That allows for inclusive comparison between start and end, however it comes with the disadvantage of not being able to subtract the two values and get a whole 24 hours. Thus, it is usually better to simply track 00:00 of one day to 00:00 of the next day, then use exclusive comparison on the end date. (Only the start date should be compared inclusively.)
In other words, instead of:
2018-08-31T00:00:00.0000000Z <= someValueToTest <= 2018-08-31T23:59:59.9999999Z
Do this:
2018-08-31T00:00:00.0000000Z <= someValueToTest < 2018-09-01T00:00:00.0000000Z
First install below package from NuGet package manager and referenced it in your project:
Install-Package Newtonsoft.Json
Now you can easily use JsonConvert.SerializeObject(object value) method for serialize any objects to Json.
For converting DateTime to UTC use TimeZoneInfo.ConvertTimeToUtc(DateTime dateTime) method.
In your case:
DateTime date = DateTime.Parse("2018-08-31");
DateTime dateTimeToUtc = TimeZoneInfo.ConvertTimeToUtc(date);
string dateInJson = JsonConvert.SerializeObject(dateTimeToUtc);
the variable dateInJson will have value like 2018-08-30T19:30:00Z.
Remove the Z
string start = "2018-08-31";
string end = "2018-08-31";
DateTime startDate = Convert.ToDateTime(start + "T00:00:00");
DateTime endDate = Convert.ToDateTime(end + "T23:59:59");
Console.WriteLine(startDate); // 8/31/2018 12:00:00 (Local)
Console.WriteLine(startDate.ToUniversalTime()); // 8/31/2018 5:00:00 (UTC)
Console.WriteLine(endDate); // 8/31/2018 11:59:59 (Local)
Console.WriteLine(endDate.ToUniversalTime()); // 9/1/2018 4:59:59 (UTC)
In case you are sending dynamic linq like me, you'd need datetime in a text form.
If you are dealing with UTC then:
//specify utc just to avoid any problem
DateTime dateTime = yourDateTime.SetKindUtc();
var filterToSendToApi = $"CreatedTime>={dateTime.ToStringUtc()}"
helpers:
public static string ToStringUtc(this DateTime time)
{
return $"DateTime({time.Ticks}, DateTimeKind.Utc)";
}
public static DateTime SetKindUtc(this DateTime dateTime)
{
if (dateTime.Kind == DateTimeKind.Utc)
{
return dateTime;
}
return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}

I want to convert date "2018-05-18 17:16:24.570" to "7/26/2018, 10:42 AM" format in C#

I am retrieving the date as a string from the database and then need to convert it. So that prints in a different format.
I am using
string date = dr[2].ToString();
date = DateTime
.ParseExact(date,"yyyy-MM-dd hh:mm:ss.fff tt ",new CultureInfo.InvariantCulture("enUS"));
But this does not work:
System.FormatException: 'String was not recognized as a valid
DateTime.'
If you work with string you can put ParseExact followed by ToString:
string date = "2018-05-18 17:16:24.570";
// 5/18/2018 05:16 PM
date = DateTime
.ParseExact(date, "yyyy-M-d H:m:s.fff", CultureInfo.InvariantCulture)
.ToString("M/dd/yyyy hh:mm ttt", CultureInfo.GetCultureInfo("en-US"));
However, it seems you are working with DataReader (dr[2] fragment); if it's your case, Convert is a better option than ParseExact (providing that RDBMS has corresponding Date field):
string date = Convert
.ToDateTime(dr[2])
.ToString("M/dd/yyyy hh:mm ttt", CultureInfo.GetCultureInfo("en-US"));
Edit: If you want to change time from UTC to a TimeZone you can try TimeZoneInfo (see all available Time Zones here) e.g.
//TODO: Put the right Time Zone Id here
// Or should it be "Arabian Standard Time"? I've tried to guess
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Atlantic Standard Time");
string date = TimeZoneInfo
.ConvertTimeFromUtc(Convert
.ToDateTime(dr[2]), zone)
.ToString("M/dd/yyyy hh:mm ttt", CultureInfo.GetCultureInfo("en-US"));

Get origin time from a datetime string with offset

If I run:
// 7:10 am at a location which has a +2 offset from UTC
string timeString = "2011-06-15T07:10:25.894+02:00";
DateTime time = DateTime.Parse(timeString);
It gives me time = 6/14/2011 10:10:25 PM. This is the local time where I am at (Pacific time i.e. UTC -7).
Is there an elegant way of getting the local time at the origin i.e. 6/15/2011 07:10:25 AM?
You can use TimeZoneInfo:
DateTime localTime = DateTime.Now;
TimeZoneInfo targetTimeZone =
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime targetTime = TimeZoneInfo.ConvertTime(localTime, targetTimeZone);
Actually, the ConvertTimeBySystemTimeZoneId method would be even more succinct:
DateTime targetTime =
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(localTime, "Eastern Standard Time");
You can get information for time zones available using TimeZoneInfo.GetSystemTimeZones().
The DateTimeOffset structure seems to be built to specifically handle timezones. It includes most of the functionality of the DateTime type.
string timeString = "2011-06-15T07:10:25.894+02:00";
DateTimeOffset time = DateTimeOffset.Parse(timeString);
As this article illustrates, you should DateTimeOffset instead of DateTime whenever you need to unambiguously identify a single point in time.
Lock into using TimeZoneInfo - http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx to do conversions. FindSystemTimeZoneById and ConvertTimeFromUtc should be enough. You may need to convert your local DateTime to UTC first with DateTime.ToUniversalTime.
You can format the way DateTime is Parse.
For example, if I want the DateTime to be format in french Canadian format :
IFormatProvider culture = new CultureInfo("fr-CA", true);
DateTime dt = DateTime.ParseExact(dateString, "dd-MM-yyyy", culture);
You can do it the same way for a en-US culture and add the time format to specify the format you want ...

How to represent the current UK time?

I'm facing an issue while converting dates between my server and client where both is running in Germany. The Regional settings on the client machines could be set to both UK or Germany.I recieve a date from the server which is CET format, and I need to represent this time on UI as UK time. For example a time recieved from server like say, 01/07/2010 01:00:00 should be represented on the UI as 01/07/2010 00:00:00. I have written a converter for this purpose, however while running it 'am getting a time difference of 2 hours.Below is the code, please can you help?
public class LocalToGmtConverter : IDateConverter
{
private readonly TimeZoneInfo timeZoneInfo;
public LocalToGmtConverter()
: this(TimeZoneInfo.Local)
{
}
public LocalToGmtConverter(TimeZoneInfo timeZoneInfo)
{
this.timeZoneInfo = timeZoneInfo;
}
public DateTime Convert(DateTime localDate)
{
var utcKind = DateTime.SpecifyKind(localDate, DateTimeKind.Utc);
return utcKind;
}
public DateTime ConvertBack(object fromServer)
{
DateTime serverDate = (DateTime)fromServer;
var utcOffset = timeZoneInfo.GetUtcOffset(serverDate);
var uiTime = serverDate- utcOffset;
return uiTime;
}
}
I think you're converting to UTC (instead of UK) time. Since there is still summer time in Central Europe (event if the temperatures say otherwise), the difference is +2 hours until October, 31st.
If you know that you're converting from Germany to UK (i.e. CEST to BST in summer and CET to GMT in winter), why you don't just subtract 1 hour?
If you want the time zone information for UK, you can construct it using
var britishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Then you could convert the date using
var newDate = TimeZoneInfo.ConvertTime(serverDate, TimeZoneInfo.Local, britishZone);
This is what I do:
var BritishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime dt = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified);
DateTime DateTimeInBritishLocal = TimeZoneInfo.ConvertTime(dt, TimeZoneInfo.Utc, BritishZone);
I needed to add the SpecifyKind part or the ConvertTime throws an exception
Use TimeZoneInfo.ConvertTime to convert original input timezone (CET) to target timezone (UK).
public static DateTime ConvertTime(
DateTime dateTime,
TimeZoneInfo sourceTimeZone,
TimeZoneInfo destinationTimeZone
)
Full guidance on MSDN here:
Converting Times Between Time Zones
Modified code sample from MSDN:
DateTime ceTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
TimeZoneInfo ceZone = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");
TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Console.WriteLine("{0} {1} is {2} GMT time.",
ceTime,
ceZone.IsDaylightSavingTime(ceTime) ? ceZone.DaylightName : ceZone.StandardName,
TimeZoneInfo.ConvertTime(ceTime, ceZone, gmtZone));
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("The registry does not define the required timezones.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the required timezones has been corrupted.");
}
The better approach to deal with local times is store them in unified representation such as UTC.
So you can convert all input times to UTC (via .ToUniversalTime()), and store (or transmit) its value. When you need to show it just convert back by using .ToLocalTime().
So you avoid rquirements to know which time zone was original value and can easily show stored value in different timezones.
Also you can avoid incoming troubles where you have to write specific logic for processing time in next timezone trying to figure out how to convert them amongs all available.
I realize the question is for C#, but if all you want to do is a single conversion you can do this from the PowerShell command line:
$d = [DateTime]::Parse("04/02/2014 17:00:00")
$gmt = [TimeZoneInfo]::FindSystemTimeZoneById("GMT Standard Time");
[TimeZoneInfo]::ConvertTime($d, $gmt, [TimeZoneInfo]::Local)
This script would convert 17:00 UK time into your local time zone.
For me, that would be CST. It's interesting to note that if I had set the date to 03/27/2014, the result would be different because the UK daylight saving time kicks in on different dates that the US.

Categories