I've got input date time strings which look like this: 2015-01-28 17:55:43. The problem is that they are in UTC+8 (or some other shift). I need those strings parsed and processed properly into UTC, regardless of the timezone where the software runs.
My problem is that DateTime.Parse returns local time, not UTC time, and I don't see a way to specify shift when parsing the string.
My current solution to this looks something like this:
add.LastUpdatedTime = new DateTime((DateTime.Parse(text) - new TimeSpan(0, 8, 0, 0)).Ticks,DateTimeKind.Utc);
This is ugly, and I'm not sure that it will work well in all circumstances.
Is there a better way of doing this?
Given that you have a local time and an offset, I'd suggest representing that in DateTimeOffset. So:
DateTime localTime = DateTime.ParseExact(...);
DateTimeOffset offsetTime = new DateTimeOffset(localTime, offset);
Then you still know the local time, but you can get the UTC equivalent when you want it. Basically it preserves all the information you have.
As an alternative, you could use Noda Time which represents the same information in OffsetDateTime. You'd use a LocalDateTimePattern to parse the value to a LocalDateTime, then use the WithOffset method to convert to an appropriate OffsetDateTime.
Write a sample program, and output the following:
Console.WriteLine(DateTime.Now.ToString("o"));
Look at that format, and use it as a template for patching up the string times coming in. For even more viable string options, look at DateTime.ToString Method ... I'll bet some variant on there will work out for you (e.g., play around with a format having "zzz" on the end, which will generate the UTC offset for a local time, e.g., "HH:mm:ss.ffffzzz" as shown in the page linked).
Also look at DateTime.Parse Method in the examples ... notice the string "2008-09-15T09:30:41.7752486-07:00" containing a UTC offset of -7 (America/Denver) indicated as being valid for parsing.
Related
I need a way to convert this date:
2019-11-07T13:30:00+05:30
to utc.
While also taking into account that it has +05:30
https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
string dateEnd = "2019-11-07T13:30:00+05:30";
DateTime converted = Convert.ToDateTime(dateEnd);
It converts it to this date:
29-Aug-19 9:00:00 AM
dateEnd="2019-11-07T13:30:00+05:30";
matchObject.DateEnd = Convert.ToDateTime(dateEnd).ToUniversalTime();
Okay, as a warning ahead: Dealing with timezones can be madening. I try to avoid it whever I can. Luckily in .NET, we can for most cases.
Internally DateTime stores the amount of Ticks since the start of the Unix Epoch (1/1/1970). Any string and any other property you see? Those are just a interpretation of that one value.
The ToString() and Parse() functions are really good at their job. If not given another culture, they will retreive the current Culture set for windows (or their Thread). For DateTimes it will also get your local timezones to factor into the display (as nessesary).
Now the debugger is just a programm too. And it will of course display the average DateTime it is viewd from your Windows current Timezone. Or rather the timezones used by the user this programm runs in - wich can be a temporary/compilation only user with all kinds of oddities.
With the Input string the timezone of Origin is clearly noted. I can not remember having seen that Syntax, but it is propably like providing a specific port for a WebRequest. No guessing or implying of values involved. And it is accepted by Parse, so whatever :)
If you get a DateFrom a UTC related function, it will set the Kind property to UTC. Wich should fix the whole "Display in Local Timezone" thing.
I've been struggling with this for a bit so I'll punt to SO.
I have an app where I need to parse strings into datetimes. The strings look like this:
"201503131557"
(they will always be this format "yyyyMMddHHmm") and always be in Central Standard Time (or Central Daylight Time depending on the date)even though they don't specify it.
When I parse them I understand that it parses them into local time. I'm running on Azure PaaS and don't want to change it to run in CST just to support this operation.
How do i write code that works both locally and in Azure PaaS that will correctly parse these dates into DateTimes setting their timezone to CST?
Here is a quick unit test I wrote to prove Matt Johnson's answer.
[TestMethod]
public void DateTests()
{
var unSpecDt = DateTime.ParseExact("201503131557", "yyyyMMddHHmm", CultureInfo.InvariantCulture);
var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var utcDt = TimeZoneInfo.ConvertTimeToUtc(unSpecDt, tz);
var offset = tz.GetUtcOffset(unSpecDt);
var dto =new DateTimeOffset(unSpecDt, offset);
var cstDt = dto.DateTime;
Assert.IsTrue(cstDt.Hour - utcDt.Hour == offset.Hours);
}
To parse the string, since you have only the date and time, and you know the specific format the strings will be in, do this:
DateTime dt = DateTime.ParseExact("201503131557", "yyyyMMddHHmm", CultureInfo.InvariantCulture);
The resulting value will have its Kind property set to DateTimeKind.Unspecified (not local time, as you thought). That is to be expected, as you provided no information regarding how this timestamp is related to UTC or local time.
You said the value represents time in Central Standard Time. You'll need a TimeZoneInfo object that understands that time zone.
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
Note that this identifier represents the Central Time observed in the USA, including both CST or CDT depending on which is in effect for the given value (despite the word "Standard" in its name). Also note that it valid on Windows operating systems only. If you wanted to use .NET Core on some other OS, then you'd need to pass the IANA identifier "America/Chicago" instead (or use my TimeZoneConverter library to use either identifier on any platform).
The next step is to figure out what you want to do with this value. You might do a few different things with it:
If you want to convert it to the equivalent UTC value, represented as a DateTime, then you can do this:
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
If you want a DateTimeOffset representation which holds the input you gave and the offset from UTC as it related to US Central Time, then you can do this:
TimeSpan offset = tz.GetUtcOffset(dt);
DateTimeOffset dto = new DateTimeOffset(dt, offset);
Keep in mind that it's possible for the input time is invalid or ambiguous if it falls near a DST transition. The GetUtcOffset method will return the standard offset in such cases. If you want different behavior, you have more code to write (out of scope for this post).
There are other things you might do, all of which are provided by the TimeZoneInfo class.
Note that "Azure PaaS" might refer to a few different things, and while there is a setting called WEBSITE_TIME_ZONE in Azure App Service - I don't recommend you lean on it. Consider it a last resort to be used only when you can't control the code. In most cases, it is better off writing your code to never depend on the time zone setting of the system it runs on. That means never calling DateTime.Now, or TimeZoneInfo.Local, DateTime.ToLocalTime, or even DateTime.ToUniversalTime (since it converts from the local time zone), etc. Instead, rely upon methods that work explicitly with either UTC or a specific time zone or offset. Then you will never need to care about where your app is hosted.
Lastly, understand that neither the DateTime or DateTimeOffset types have any capability of understanding that a value is tied to a specific time zone. For that, you'd need to either write your own class, or look to the Noda Time library whose ZonedDateTime class provides such functionality.
You can use:
DateTime.ParseExact(...)
public static DateTime ParseExact (string s, string format, IFormatProvider provider);
This datetime do not have any metadata about timezone. You can convert to UTC and then you will be sure that you are able to convert to all timezones.
Use the DateTime.TryParseExact(...) method with DateTimeStyles.RoundtripKind to avoid conversion.
DateTime dt;
DateTime.TryParseExact("201503131557", "yyyyMMddHHmm", null, System.Globalization.DateTimeStyles.RoundtripKind, out dt);
If you need to convert you will need to go to UTC then use the conversion methods of TimeZoneInfo with TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time").
I am using Facebook C# SDK to get some data from my Facebook page.
When I get objects of data, at that time I get one field:
created_time : 2014-05-23T11:55:00+0000
As it is not same as my current time how do I convert it to my current time or to standard UTC time?
For me the code:
DateTime.Parse("2014-05-23T11:55:00+0000").ToString()
returns
2014-05-23 12:55:00
Because 'DateTime.Parse()` understands the timezone in this string, and by default produces a local time. My timezone being Irish Summer Time, one hour ahead of UTC, that means 2014-05-23T12:55:00 for me, for you it'll be a different time depending on your timezone.
For the converse, to get the time parsed in UTC (more useful for behind-the-scenes web stuff or storage, rather than user interface), use DateTime.Parse("2014-05-23T11:55:00+0000").ToUniversalTime()
If you need to deal with timezones other than local to the machine the code is running on, or UTC, then you will need to use DateTimeOffset, with the exception that DateTimeParse will handle other timezones in the string, but from that point on only has the concepts of "local time", "universal time" and "unknown timezone".
I would use DateTimeOffset.ParseExact, specifying the format string an the invariant culture:
DateTimeOffset value = DateTimeOffset.ParseExact(text, "yyyy-MM-dd'T'HH:mm:ssK",
CultureInfo.InvariantCulture);
I strongly recommend this over using DateTime.Parse for the following reasons:
This always uses the invariant culture. It's explicitly stating that you don't want to use the local culture, which might have a different default calendar system etc
This specifies the format exactly. If the data becomes "10/06/2014 11:55:00" you will get an exception, which is better than silently guessing whether this is dd/MM/yyyy or MM/dd/yyyy
It accurately represents the data in the string: a date/time and an offset. You can then do whatever you want with that data, but separating the two steps is clearer
The first two of these can be fixed by using DateTime.ParseExact and specifying the culture as well, of course.
You can then convert that to your local time zone, or to any other time zone you want, including your system local time zone. For example:
DateTimeOffset localTime = value.ToLocalTime(); // Applies the local time zone
or if you want a DateTime:
DateTimeOffset localTime = value.ToLocalTime().DateTime;
It's just one extra line of code, but it makes it clearer (IMO) what you're trying to do. It's also easier to compare DateTimeOffset values without worrying about what "kind" they are, etc.
In fact, I wouldn't personally use DateTimeOffset or DateTime - I'd use OffsetDateTime from my Noda Time project, but that's a different matter.
I am currently using the following date filter in my WebAPI application:
json.SerializerSettings.Converters.Add(
new IsoDateTimeConverter { DateTimeFormat = "dd-MM-yyyy hh:mm" });
I started to use this as my front end could not understand the dates. If I remember correctly it was due to the way milliseconds were formatted with too many digits.
What I need is to get the date into a format like this:
1288323623006
Can someone suggest how I can do this using the serializer. Is this different from the default?
You don't want to use IsoDateTimeConverter at all - you possibly want to use JavaScriptDateTimeConverter. That will convert it into new Date(...) with the right value - but I believe it really will include the new Date(...) part. If you don't want that, you'll probably need to write your own converter.
It shouldn't be too hard to write a converter - although you need to decide how to handle the different kinds of DateTime. For example, if you're asked to convert a DateTime with a Kind of Unspecified, do you want to assume it's actually already in UTC, or already in the system local time zone, or something else?
Once you've got an appropriate "instant" in time, you just need to find the number of milliseconds between that and the Unix epoch (1st January 1970 00:00:00, UTC) and convert that number of milliseconds into a string.
I think that's what you want
private static readonly long DatetimeMinTimeTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
long b = (long)((Calendar1.SelectedDate).ToUniversalTime().Ticks - DatetimeMinTimeTicks) / 10000;
In C# if I want to parse a datetime, but some times I just have either a date and not a time component or no date but a time component, how would I do this? Usually when you leave out the time component, it automatically assumes that the time is 12:00AM. But I don't want this. If the time component is missing then I just want the DateTime to store a date only and the leave the time component off.
The value of a DateTime internally is just an UInt64 (ulong in C#) that stores the number of ticks since some date in the past, so whether you like it or not, the time component will always be there.
If you only need to display certain parts, just use any of the format strings (examples are for "en-us" culture):
DateTime.Now.ToString("d"); // 5/26/2009
DateTime.Now.ToString("t"); // 4:56 PM
The complete reference: http://msdn.microsoft.com/en-us/library/az4se3k1.aspx
It's not possible to have a DateTime without a time component. You could store a boolean flag along with it in a struct to store data about existence of that component. However, there's no way to use the automatic parsing routine to distinguish between a DateTime string with a time specified as 12:00 PM and a nonexistent one.
If it really bugs you you can always create a wrapper class that can hide the time portions of the datetime class.
No you will have the time component no matter what. The best you can do is access the Date property on your DateTime object if you really have to.
http://msdn.microsoft.com/en-us/library/system.datetime.date.aspx
DateTime by definition stores a date and a time such that it cannot just represent one of them without representing the other. If you only want the date (or only the time), parse out the information you need and discard the rest of it.
As mentioned before DateTime will always have a Date and a Time part of it if you only want a single part use the way described by the others
DateTime date = DateTime.Parse("2009-11-30);
date.Year; = 2009
date.Month; = 11
date.Day; = 30
date.Hour; = 0
and so on
The thing you must be aware is that all of these methods will only return an integer.
If you want to know all the possible ways to parse a string John Sheehan has put together a great Cheat Sheet wit all possible ways to parse and manipulate dates, and other strings for that matter.
You could have a class that stores a DateTime and determines if the time was ever set or if just the date was set and return values accordingly.
Use
DateTime date = new DateTime();
date = DateTime.Parse("1/1/2001");
to set the date, then use
date.ToShortDateString();
or
date.Year;
date.Month;
date.Day;
to get what you need. Hope that helps!
A DateTime object is always stores a date + a time, not just one. You can always choose to work only with the date part, i.e. only use properties like Year, Month, DayOfWeek. But underneath there will aways be some stored time.
It is very dangerous to assume that the date portion of a DateTime is necessarily the date you are expecting. As pointed-out, DateTime always includes and considers the time aspect, even when you don't see it.
This is a big problem when you have data stored in different time-zones (and particularly if knowledge of that offset is not also kept, because it is assumed that what is being stored is a Date, not a date-with-time).
You may store a birthdate as '01/01/2000 00:00:00' during Summer-Time, which then is stored in UCT as '31/12/1999 23:00:00'. When you then read that birth-date later, the date portion is now a day early.
Best to create your own type. Strange that Microsoft didn't think it worth having a Date type.