Issue with datetime parsing - c#

When I tried to parse the "2017-09-25T11:06:55+00:00" date string using TryParse method, I get the following output:
{9/25/2017 7:06:55 AM}
So, it's looks like 11 a.m. is getting converted into 7 a.m. Not sure why is this happening this? Is it because of +00:00??
What do I need to do so that parsed Datetime output is same: i.e. {9/25/2017 11:06:55 AM} ?
I tried using Current locale/culture and DateTime Styles. Assume Local but no luck.
(Note: I'm in the eastern time-zone)
Thanks.

You are using the UTC timezone (+00:00), but apparently, you or your PC is in -04:00 timezone.

If you can use DateTimeOffset, then I tend to prefer it. You get time zone info preserved, and you have access to both local and UTC datetime properties off this object.
var dt = DateTimeOffset.Parse("2017-09-25T11:06:55+00:00");
Console.WriteLine(dt.DateTime); // 9-25 at 11:06
Console.WriteLine(dt.UtcDateTime); // 9-25 at 11:06
Console.WriteLine(dt.LocalDateTime); // 9-25 at 07:06
If you know you're always going to be dealing with UTC, you can just parse by adjusting to universal like so:
var dt = DateTime.Parse("2017-09-25T11:06:55+00:00", CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal);
Console.WriteLine(dt); // 9-25 at 11:06

When you parse it initially it's the correct value, it's just now adjusted to be in your timezone. You can force it with ToUniversalTime :
DateTime.Parse("2017-09-25T11:06:55+00:00").ToUniversalTime().ToString("yyyy/MM/dd HH:mm:ss tt")
output
"2017/09/25 11:06:55 AM"

You want to parse correctly UTC DateTime and to have 9/25/2017 11:06:55 AM instead of 9/25/2017 7:06:55 AM. +00:00 is not correct UTC format, you need to change it to "2017-09-25T11:06:55z".
Here is working example

Related

DateTime.ToString() not converting time

Looks like time is automatically getting changed during conversion.
My input is 17:15:25. However, it gets converted to 13:15:25
What could be the reason?
string testDate = Convert.ToDateTime("2016-03-24T17:15:25.879Z")
.ToString("dd-MMM-yyyy HH:mm:ss", CultureInfo.InvariantCulture);
The result I get for testDate is : 24-Mar-2016 13:15:25
The Z in your input indicates a UTC time, but the default behaviour of Convert.ToDateTime is to convert the result to your local time. If you look at the result of Convert.ToDateTime("2016-03-30T17:15:25.879Z").Kind you'll see it's Local.
I would suggest using DateTime.ParseExact, where you can specify the exact behaviour you want, e.g. preserving the UTC time:
var dateTime = DateTime.ParseExact(
"2016-03-30T17:15:25.879Z",
"yyyy-MM-dd'T'HH:mm:ss.FFF'Z'",
CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
Console.WriteLine(dateTime); // March 30 2016 17:15 (...)
Console.WriteLine(dateTime.Kind); // Utc
You can then convert that value to a string however you want to.
Of course I'd really suggest using my Noda Time project instead, where you'd parse to either an Instant or a ZonedDateTime which would know it's in UTC... IMO, DateTime is simply broken, precisely due to the kind of problems you've been seeing.
When you use Convert.ToDateTime (which uses DateTime.Parse internally) with Z (which means Zulu time), this method adds your current time zone offset to that DateTime value.
Looks like your current time zone is UTC -04:00 right now and that's why method returns 4 hours back as a result.
I would suggest to use DateTime.ParseExact with AdjustToUniversal and AssumeUniversal styles for prevent Kind conversion as Jon answered.
From AdjustToUniversal
Date and time are returned as a Coordinated Universal Time (UTC). If
the input string denotes a local time, through a time zone specifier
or AssumeLocal, the date and time are converted from the local time to
UTC. If the input string denotes a UTC time, through a time zone
specifier or AssumeUniversal, no conversion occurs. If the input
string does not denote a local or UTC time, no conversion occurs and
the resulting Kind property is Unspecified.
Because of the CultureInfo.InvariantCulture.
You are converting a date in your GMT
Convert.ToDateTime("2016-03-24T17:15:25.879Z")
And then you are converting it to string in an invariant culture
ToString("dd-MMM-yyyy HH:mm:ss",CultureInfo.InvariantCulture);
You should use DateTime.ParseExact, and then use the invariant culture in the conversion.

Date conversion

I need help to convert current date to "Tue Nov 4 00:00:00 UTC+0530 2014" date format
using C#.
Say I have date like : DateTime dt = DateTime.Now;
Now, how can I convert it in mentioned format.
DateTime.ToString(string) allows you to specify a format for your date. You can construct a custom format using Custom Date and Time Format Strings.
I feel like taking risk to answer your question but anyway..
A DateTime doesn't have any implicit format. It just have date and time values etc.. That's why it is not possible to have any format. But string representations of them can have a format. Formatting a DateTime is easy, just need to use DateTime.ToString() method with a specific culture. (In your case looks like InvariantCulture is a good candidate)
DateTime dt = DateTime.Now;
dt.ToString("ddd MMM d HH:mm:ss 'UTC+0530' yyyy", CultureInfo.InvariantCulture);
returns
Tue Nov 4 14:20:36 UTC+0530 2014
AFAIK, time zone abbreviations are not standardized and that's why there is way to parse them besides literal string delimiter. Also since a DateTime doesn't keep offset value, you need also parse it as a literal string delimiter
If you would want to +05:30 instead +0530 as a result, "zzz" custom format specifier would be a nice choice since it gets + or - sign, hours and minutes part offset of local operating system's time zone from UTC.
Based upon your suggestions, I build this code
DateTimeOffset localTime = DateTimeOffset.Now;
string.Format("{0:ddd MMM d HH:mm:ss} UTC+{1} {0:yyyy}", localTime, localTime.Offset.ToString("hhmm"));
and its generating correct format:
"Tue Nov 4 18:25:48 UTC+0530 2014"

C# datetime parse issue

When trying to convert date/time from string to DateTime, I'm not getting the correct value.
DateTime testDate = DateTime.ParseExact("2012-08-10T00:51:14.146Z", "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
And my result is 2012-08-09 8:51:14 PM. Why is it being offset? I just want it to be the same value going in.
You are parsing the UTC date but the DateTime.Kind is local.
You should parse with DateTimeStyles.AdjustToUniversal to mark the Kind as Utc.
DateTime testDate = DateTime.ParseExact("2012-08-10T00:51:14.146Z", "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
Trace.WriteLine(testDate); // 8/9/2012 8:51:14 PM
Trace.WriteLine(testDate.ToString()); // 8/9/2012 8:51:14 PM
Trace.WriteLine(testDate.ToUniversalTime()); // 8/10/2012 12:51:14 AM
Trace.WriteLine(testDate.Kind); // Local
testDate = DateTime.ParseExact("2012-08-10T00:51:14.146Z", "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
Trace.WriteLine(testDate);// 8/10/2012 12:51:14 AM
Trace.WriteLine(testDate.ToString());// 8/10/2012 12:51:14 AM
Trace.WriteLine(testDate.ToUniversalTime());// 8/10/2012 12:51:14 AM
Trace.WriteLine(testDate.Kind); // Utc
Aware this is an answer many years later, but came across this today and once I worked out my problem wanted to add some context I didn't see in other answers.
Going back to the OPs code snippet the reason it doesn't do what the OP expected of taking a UTC time string and storing it as a UTC DateTime is because the DateTimeStyles.AssumeUniversal only specifies that the input string is a UTC string. By default C# will create DateTime's as a DateTimeKind.Local. This was pointed out in another answer. This means the time is converted from UTC to Local time.
To make sure that your end result ends up being a UTC DateTime you need to use the DateTimeStyles of DateTimeStyles.AdjustToUniversal. This was also mentioned in other answers. However, if your input string doesn't have an obvious timezone then it may be assumed to be local and then converted from Local to UTC.
Luckily DateTimeStyles is actually a flag enum meaning we can use both the above options at the same time. E.g:
DateTime testDate = DateTime.ParseExact("2012-08-10T00:51:14.146Z", "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
You should use DateTimeStyles.AdjustToUniversal. The input DateTime is already universal, and the AdjustToUniversal enum option will convert the input to local time though you will get a resultant Kind of DateTimeKind.Unspecified.
What is your server timezone, if you use AssumeUniversal it will convert your input time to UTC time.
You probably in EST then.
I propose simply that you want to use .AssumeLocal instead of .AssumeUniversal.
You have a time stamp with unknown time zone, and if you know that the time stamp refers to an event that happened in your local time zone, then you should tell the parse to assume that the time stamp is local to you (i.e. in your time zone).
By using .AssumeUniversal, you are instructing the parser to treat the time stamp as if it was a UTC time stamp, which when you display it using your local time zone, it's automatically offset by that amount.
Edit:
One important thing: The capital "Z" in the time stamp suggests it is a UTC time stamp, which means you do want to treat it as Universal. If you want to treat it as a local time stamp, you should remove the Z from the time stamp and the corresponding parse string.
Reference: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx#KSpecifier

MVC C# DateTime formatting fix needed

As you can see in the below screen shot. I have Date which is 7/12/2011 12:00:00 AM. Date is described wrong even if I format it. 7 should be the day and 12 is the month.
How I fix that to get proper formatting for yellow return string?
In the below screen shot the Date is 28/12/2011 11:00 where 28 is day and 12 is month. Trying to convert that string into DateTime to save into SQL Server DateTime field but gives conversion problem. Anyone tell me why is that and How to fix it?
Solution:
I solved problem like below. When I want saving date in SQL Server 2008 r2 the default was saved like 2011-08-12 11:00:00.000 which was causing problem. I changed that formatting Date when it was going to be saved in SQL like below and it worked
DateTime n = Convert.ToDateTime(start_date);
var h = String.Format("{0:dd/MM/yyyy}", n);
if (start_date != "")
{
changedEvent.start_date = Convert.ToDateTime(h);
}
Output now is 2011-12-08 11:00:00.000. Do you think any clean work around?
You should call DateTime.ParseExact(start_date, "dd/MM/yyyy", CultureInfo.InvariantCulture)
Try:
DateTime.ParseExact(str, "dd/MM/yyyy HH:mm:ss TT", null); //28/12/2011 11:00:00 AM
DateTime.ParseExact(str, "dd/MM/yyyy HH:mm", null); //28/12/2011 11:00
I think you are addressing the wrong problem. If you want DateTime to recognize your locale date format, then you should make sure the servers date locale is set for your local one. Then, DateTime will convert the date correctly without conversion.
If that's not possible (say you're using a shared server in a different locale) then the ParseExact method would be one solution, but it will only fix some of the problem. For instance, dates posted and model bound will attempt to parse in the servers locale format.
You may need to set your locale explicitly, using something like this:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("es-MX");

Converting the string "20111027" to a DateTime with a timezone of GMT

I have a string in this format: "20111027", i.e. of the general format: "yyyyMMdd".
How do I convert this to a DateTime having the timezone GMT?
This code does some conversion, but it's unclear what timezone would be used:
DateTime date = DateTime.ParseExact(dateString, "yyyyMMdd",
CultureInfo.InvariantCulture);
Use a DateTimeStyles of AssumeUniversal:
DateTime date = DateTime.ParseExact(dateString, "yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal);
From the docs of DateTimeStyles.AssumeUniversal:
If no time zone is specified in the parsed string, the string is assumed to denote a UTC.
Sounds like exactly what you want :)
(Alternatively you could use Noda Time and parse it to a LocalDate. It only represents a date, after all, so why use a type which cares about times and time zones? :)
From the documentation:
If s does not represent a time in a particular time zone and the parse operation succeeds, the Kind property of the returned DateTime value is DateTimeKind.Unspecified.
You can change the Kind using DateTime.SpecifyKind:
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);

Categories