C# Datetime.ParseExact for a parsing a string containing UTC text - c#

I have a date time string that looks like this:
13.08.2014 17:17:45.000 UTC-60
I am trying to parse it into a C# date time object but it is not working as I expected.
Here is what I tried:
DateTime.ParseExact(dateToParse, "dd.MM.yyyy hh:mm:ss.fff Z", CultureInfo.InvariantCulture);
DateTime.ParseExact(dateToParse, "dd.MM.yyyy hh:mm:ss.fff UTC", CultureInfo.InvariantCulture);
DateTime.ParseExact(checkInDate, "dd.MM.yyyy hh:mm:ss.fff", CultureInfo.InvariantCulture);
They all return same error
{"String was not recognized as a valid DateTime."}
Some of the existing questions like this did not help either.
Any suggestions?

First, your main problem there with parsing is that your're using hh for 24h format. That should be HH. This should work:
DateTime.ParseExact("13.08.2014 17:17:45.000", "dd.MM.yyyy HH:mm:ss.fff", null, System.Globalization.DateTimeStyles.AssumeUniversal)
As for the UTC part, that's not standard format, so I suggest you to create a helper method that splits this string in 2, parse the first part as provided above, and parse the number after UTC and either add that to your DateTime:
myDate.AddMinutes(Int32.Parse("-60"))
Or create a DateTimeOffset. In either case, you must parse them individually.

How much control do you have over the time format.
.Net datetime parsing expects 2 things that are wrong with the current time format that you are trying to parse:
First, you have 24 hour time, so in your format you must use HH for hours, the lower case hh implies that the hours will be 12 hour format.
The UTC issue is another one that will require you to modify the string first, .Net expects timezone information in the form of HH:mm, so the following string and conversion will work, notice the key differences
var dateToParse = "13.08.2014 17:17:45.000 -01:00";
var value = DateTimeOffset.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff zzz", CultureInfo.InvariantCulture);
Use DateTimeOffset to maintain the TimeZone information
HH to map the hours
zzz to map the timezone information
So, to address you question, how can we parse the string into a format that we can then use to parse into a date time:
dateToParse = "13.08.2014 17:17:45.000 UTC-60";
string utc = null;
if (dateToParse.Contains("UTC"))
{
var tokens = dateToParse.Split(new string[] { "UTC" }, StringSplitOptions.None);
dateToParse = tokens[0];
utc = tokens[1];
int minutes = int.Parse(utc);
var offset = TimeSpan.FromMinutes(minutes);
bool negative = offset.Hours < 0;
dateToParse += (negative ? "-" : "") + Math.Abs(offset.Hours).ToString().PadLeft(2,'0') + ":" + offset.Minutes.ToString().PadLeft(2,'0');
}
var value = DateTimeOffset.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff zzz", CultureInfo.InvariantCulture);
To be honest, that was more complicated than I thought, there might be some regex expressions that might help, but this first principals approach to manipulating the string first works with your string.
Finally, now that we have a DateTimeOffset value, you can easily convert this into any local or other timezone without too much hassel, if you need to:
var asUtc = dateValue.UtcDateTime;
var asLocal = dateValue.LocalDateTime;
var asSpecific = dateValue.ToOffset(TimeSpan.FromHours(10)).DateTime;

Related

C# parse DateTime String to time only

I am new to C# and I have a string like "2021-06-14 19:27:14:979". Now I want to have only the time "19:27:14:979". So do I parse the string to a specific DateTime format and then convert it back to a string or would you parse or cut the string itself?
It is important that I keep the 24h format. I don't want AM or PM.
I haven't found any solution yet. I tried to convert it to DateTime like:
var Time1 = DateTime.ParseExact(time, "yyyy-MM-dd HH:mm:ss:fff");
var Time2 = Time1.ToString("hh:mm:ss:fff");
But then I lost the 24h format.
Your code is almost working, but ParseExact needs two additional arguments and ToString needs upper-case HH for 24h format:
var Time1 = DateTime.ParseExact("2021-06-14 19:27:14:979", "yyyy-MM-dd HH:mm:ss:fff", null, DateTimeStyles.None);
var Time2 = Time1.ToString("HH:mm:ss:fff");
Read: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings#uppercase-hour-h-format-specifier
Instead of passing null as format provider(means current culture) you might want to pass a specifc CultureInfo, for example CultureInfo.CreateSpecificCulture("en-US").
You can just split it at the blank and take the last part like this
var timestamp = "2021-06-14 19:27:14:979";
var timePart = timestamp.Split(' ')[1];
in your case that seems easier than parsing into a DateTime and back into a string.

Convert String to DateTime(yyyy-mm-dd)

I'm parsing date from server, date is in this format 6/16/2016 3:15:29 PM Could you help me please convert date to 2016-06-16?
I tried:
DateTime date = DateTime.ParseExact(datestring, "MM/dd/yyyy h-m-s t", System.Globalization.CultureInfo.InvariantCulture);
string formattedDate = date.ToString("yyyy-MM-dd")
but it's giving me error.
You've got 3 problems
You're not using the correct time separators
You're using only one t when you need two
You're using two M when you only need one
Try
DateTime date = DateTime.ParseExact(datestring, "M/d/yyyy h:m:s tt", System.Globalization.CultureInfo.InvariantCulture);
string formattedDate = date.ToString("yyyy-MM-dd");
The reason you need only one M is because MM expects a leading zero. Since the values of the date and time are delimited it's better to use the single versions for month, day, minutes, and seconds because they will work for values with or without leading zeros.
To execute DateTime.ParseExact() format of the input string and the format string must be the same. try this:
DateTime date = DateTime.ParseExact(datestring, "M/dd/yyyy h:mm:ss tt", System.Globalization.CultureInfo.InvariantCulture);
string formattedDate = date.ToString("yyyy-MM-dd");
These are interesting in the given input string(6/16/2016 3:15:29 PM):
The month is represented in single digit so it should be M instead for MM. We use MM if it is specified as 06.
Same in the case of Hours too. It should be h instead for normal hh
There is a single space in between Date and Time as well as Time and PM.
So we must consider all of these while generating the Format-string for ParseExact

Converting string in yyyy-MM-ddTHH:mm:ss zzz format to DateTime

I am receiving a JSON DateTime from a web service in the following format
yyyy-MM-ddTHH:mm:ss zzz
For example:
2016-04-18T15:09:21 01:00
However, I am unable to convert this into a DateTime object. I have tried the following:
var date = DateTime.ParseExact("2016-04-18T15:09:21 01:00", "yyyy-MM-ddTHH:mm:ss zzz", CultureInfo.InvariantCulture);
var date2 = DateTimeOffset.ParseExact("2016-04-18T15:09:21 01:00", "yyyy-MM-ddTHH:mm:ss zzz", CultureInfo.InvariantCulture);
Both of these lines throw the System.FormatException exception with the message:
String was not recognized as a valid DateTime.
How can I parse 2016-04-18T15:09:21 01:00 as a DateTime object?
Unfortunately the "zzz" expects a sign on the timezone.
This will work.
var date = DateTime.ParseExact("2016-04-18T15:09:21 +01:00", "yyyy-MM-ddTHH:mm:ss zzz",System.Globalization.CultureInfo.InvariantCulture);
date.Dump();
So add a plus sign.
var dt="2016-04-18T15:09:21 01:00";
dt.Insert(20,"+").Dump();
Dmitriy has the right answer, from The "zzz" custom format specifier documentation;
The offset is always displayed with a leading sign. A plus sign (+)
indicates hours ahead of UTC, and a minus sign (-) indicates hours
behind UTC. A single-digit offset is formatted with a leading zero.
If your string is always in yyyy-MM-ddTHH:mm:ss HH:mm format, you have to manipulate it if you wanna parse it to DateTimeOffset.
I would suggest to you split your string with a white space, call DateTime.Parse and TimeSpan.Parse on those strings and use those values in a DateTimeOffset(DateTime, TimeSpan) constructor which;
Initializes a new instance of the DateTimeOffset structure using the
specified DateTime value and offset.
var str = "2016-04-18T15:09:21 01:00";
var parts = str.Split(' ');
var date = DateTime.Parse(parts[0]);
var offset = TimeSpan.Parse(parts[1]);
var dto = new DateTimeOffset(date, offset);
Now you have a DateTimeOffset as {18.04.2016 15:09:21 +01:00} and you can use it's DateTime, LocalDateTime or UtcDateTime properties whichever you want.

Adding two dates to eachother

string final = Convert.ToString(DateTime.Parse(date, System.Globalization.CultureInfo.InvariantCulture) + TimeSpan.Parse(duration));
Hi, I use the above code to add two date's to eachother. It do work very well on Windows and returns the required format yyyy-MM-dd HH:mm:ss in a correct fashion. HOWEVER, when on Linux building with Mono it returns the following format dd/MM/yyyy HH:mm:ss which is not what I want.
How can I specify that I ONLY want the first formatting and nothing else? I tried playing around with ParseExact but it did not do very well. What I've heard ParseExact should not really be needed for this?
Here is a example of input:
string date = "2014-10-30 10:00:04"; // On windows
string duration = "05:02:10"; // duration to be added to date
Greetings.
Use ToString("yyyy-MM-dd HH:mm:ss") instead of Convert.ToString.
string date = "2014-10-30 10:00:04";
string duration = "05:02:10";
DateTime dt1 = DateTime.Parse(date, CultureInfo.InvariantCulture);
TimeSpan ts = TimeSpan.Parse(duration, CultureInfo.InvariantCulture);
DateTime dtFinal = dt1.Add(ts);
string final = dtFinal.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
Convert.ToString uses your current culture's date separator, use CultureInfo.InvariantCulture.
Read: Custom Date and Time Format Strings
You can use the ToString() Method of the DateTime object.
var dt = DateTime.Now;
dt.ToString("yyyy-MM-dd HH:mm");
Using your code:
string _final = (DateTime.Parse(date, System.Globalization.CultureInfo.InvariantCulture) + TimeSpan.Parse(duration)).ToString("yyyy-MM-dd HH:mm:ss");

Convert string to Time

I have a time that is 16:23:01. I tried using DateTime.ParseExact, but it's not working.
Here is my code:
string Time = "16:23:01";
DateTime date = DateTime.ParseExact(Time, "hh:mm:ss tt", System.Globalization.CultureInfo.CurrentCulture);
lblClock.Text = date.ToString();
I want it to show in the label as 04:23:01 PM.
"16:23:01" doesn't match the pattern of "hh:mm:ss tt" - it doesn't have an am/pm designator, and 16 clearly isn't in a 12-hour clock. You're specifying that format in the parsing part, so you need to match the format of the existing data. You want:
DateTime dateTime = DateTime.ParseExact(time, "HH:mm:ss",
CultureInfo.InvariantCulture);
(Note the invariant culture, not the current culture - assuming your input genuinely always uses colons.)
If you want to format it to hh:mm:ss tt, then you need to put that part in the ToString call:
lblClock.Text = date.ToString("hh:mm:ss tt", CultureInfo.CurrentCulture);
Or better yet (IMO) use "whatever the long time pattern is for the culture":
lblClock.Text = date.ToString("T", CultureInfo.CurrentCulture);
Also note that hh is unusual; typically you don't want to 0-left-pad the number for numbers less than 10.
(Also consider using my Noda Time API, which has a LocalTime type - a more appropriate match for just a "time of day".)
string Time = "16:23:01";
DateTime date = DateTime.Parse(Time, System.Globalization.CultureInfo.CurrentCulture);
string t = date.ToString("HH:mm:ss tt");
This gives you the needed results:
string time = "16:23:01";
var result = Convert.ToDateTime(time);
string test = result.ToString("hh:mm:ss tt", CultureInfo.CurrentCulture);
//This gives you "04:23:01 PM" string
You could also use CultureInfo.CreateSpecificCulture("en-US") as not all cultures will display AM/PM.
The accepted solution doesn't cover edge cases.
I found the way to do this with 4KB script. Handle your input and convert a data.
Examples:
00:00:00 -> 00:00:00
12:01 -> 12:01:00
12 -> 12:00:00
25 -> 00:00:00
12:60:60 -> 12:00:00
1dg46 -> 14:06
You got the idea...
Check it https://github.com/alekspetrov/time-input-js

Categories