How to parse date from string using ParseExact? - c#

I'm trying to parse a date from a string formatted as the following "17/9/2020, 13:00:00" as a valid DateTime object, but after trying to use .ParseExact and setting the date pattern i'm getting the error:
String '17/9/2020, 13:00:00' was not recognized as a valid DateTime..
By using .ParseExact i'm trying to do the following:
DateTime.ParseExact(quando.quando, "dd/MM/yyy, HH:mm:ss", null)

you have 1 M too much and 1 y too few:
DateTime.ParseExact("17/9/2020, 13:00:00", "dd/M/yyyy, HH:mm:ss", null)
the format MM expects an input of always two digits for the month like 09 (september)
If you take only 1 M it will also parse a 2 digit month like december:
DateTime.ParseExact("17/12/2020, 13:00:00", "dd/M/yyyy, HH:mm:ss", null)
EDIT: taking this from Jon Skeets comment: you should probably also use a single d for days since your date string will likely exhibit the following format "7/9/2020, 13:00:00".
DateTime.ParseExact("7/9/2020, 13:00:00", "dd/M/yyyy, HH:mm:ss", null)

Your format isn't correct. See an example here:
https://dotnetfiddle.net/2ppjvX
You should use this format "dd/M/yyyy, HH:mm:ss". "MM" expects 2 digist like "09". Also 4 "y" symbols are required.

Related

System.FormatException: 'String '"2022-04-14 13:03:12"' was not recognized as a valid DateTime.'

cnn.Open();
using (StreamReader reader = new StreamReader(#"C:/Users/jhogan/Documents/Test Folder/test_import.csv"))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (lineNumber != 0)
{
var values = line.Split(',');
var date = values[0];
var sentDate = DateTime.ParseExact(date, "yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture);
await cnn.ExecuteAsync(insertFeedback, new {
#SentDate = sentDate, #RatedDate = values[1], #Rating = values[2], #Location = values[3], #Notes = values[4], #Email = values[5], #Feedback = values[6] },commandTimeout: 120,commandType: CommandType.StoredProcedure);}
I am attempting to load this data from a csv file into my database, but am running into the following error from the title. The original formatting of the date from my csv is HH:MM:SS PM/AM and my column type in the database is datetime. In my database, the datetime formatting is YYYY-MM-DD HH:MM:SS:MMM. I think this is because of the database's formatting of things, but I am genuinely not sure.
my column type in the database is datetime. In my database, the datetime formatting is YYYY-MM-DD HH:MM:SS:MMM.
You misunderstand how the database and .Net DateTime values work. If the column type or data type is DateTime, the format in the database or in memory is binary, and when you see YYYY-MM-DD HH:MM:SS:MMM that's just a convenience provided for you by your tooling. There is no need to ever try to match your string to that internal binary format.
But as for the code, the problem is the lower-case hh in the format string. We can see in the documentation the lower-case h is for 12-hour times and upper-case H is for 24 hour times. Looking at the input string 2022-04-14 13:03:12 from the error in the question title, we have a 13 in this position, which definitely puts you in upper-case H territory:
var sentDate = DateTime.ParseExact(date, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
But it's worse than that. I also see this in a comment:
the first row is 4/14/2022 1:03:12 PM
So first of all, the format string for DateTime.ParseExact() tells the format of the original input source string, not the target format for the parsed value, which is, after all, binary and not human readable anyway.
The format string to parse that value would look like this: M/dd/yyyy h:mm:ss tt. Also note the use of paired vs single characters in certain positions.
var sentDate = DateTime.ParseExact(date, "M/dd/yyyy h:mm:ss tt", CultureInfo.InvariantCulture);
But the real significance here is the variation between the error in the question title and the comment means you might have a mix of formats. That's scary. DateTime.ParseExact() uses strict parsing. If the input does not EXACTLY match the expected format you WILL get an exception.
Fortunately, there is an overload for the method that accepts multiple format strings. Even with this overload, though, you probably need to take the time to review the csv data and make sure that every possible format in the data is accounted for.
And if data for this field could be entered by random humans may God have mercy on your soul.

How to convert BigQuery Timestamp to DateTime?

I'm using Google.Cloud.BigQuery.V2 to access big query. In my table I have a field created_at which is in Timestamp(ex: 2019-08-11 11:22:22.123 UTC). When I tried to convert this field into C# datetime it gives the following output:
8/11/2019 11:22:22 PM
And when I tried to convert this into a datetime (format : yyyy-MM-dd HH:mm:ss.fffffff) it gives me the following value
2019-08-11 22:22:22.0000000
But I want my output to look like this 2019-08-11 11:22:22.1230000
Here is my code
string created_at = $"{row["created_at"]}".ToString() == null ? "" : $"{row["created_at"]}".ToString();
DateTime date = DateTime.ParseExact(created_at, "M/d/yyyy H:mm:ss tt", CultureInfo.InvariantCulture);
string newDate = date.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
Console.WriteLine (newDate);
What am I doing wrong here? How to get milliseconds?
Use
var date=(DateTime?)row["created_at"];
var text=string.Format("{0:yyyy-MM-dd hh:mm:ss.fffffff tt}", date,
CultureInfo.InvariantCulture);
or
var date=(DateTime?)row["created_at"];
var text=FormattableString.Invariant($"{date:yyyy-MM-dd hh:mm:ss.fffffff tt}");
To read a BigQueryDbType.Timestamp value and format it into a string using a 12-hour notation and AM/PM designator in English.
Explanation
The source code itself shows that calling row["created_at"] converts a BigQueryDbType.Timestamp type gets converted to a UTC DateTime. This means that this code will work :
var date=(DateTime?)row["created_at"];
The returned date contains all the information there is. If the value contains milliseconds, date will also contain milliseconds. The source code shows that the value's precision is 10 microseconds.
DateTime is a binary value, it has no format. Formats apply only when a string needs to be parsed into a DateTime value or when a DateTime value needs to be formatted as a string for display or saving to a text file, with ToString(), String.Format() or string interpolation.
For example, the o standard format specifier creates a string in the ISO8601 format :
var date=DateTime.UtcNow.ToString("o")
//2019-09-18T14:02:22.2048166Z
HH is the double digit specifier that returns a 24-hour value (0-23) while hh returns the hour between 0 and 12. When hh is used the t (AM/PM designator) should also be used, otherwise there's no way to say whether the hour is 10 AM or 10 PM.
This return 14:00 etc :
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fffffff")
//2019-09-18 14:07:48.2517651
While this returns
DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss.fffffff")
//2019-09-18 02:08:45.1001800
Which is a problem - is this AM or PM? Adding tt at the end fixes this, but the returned designator would be localized. To ensure a specific designator is used, we need to pass a CultureInfo parameter :
DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss.fffffff tt",CultureInfo.InvariantCulture)
//2019-09-18 02:10:39.9194735 PM
Putting it all together, to get the date from BigQuery and then format it as a string using AM/PM :
var date=(DateTime?)row["created_at"];
var text=string.Format("{0:yyyy-MM-dd hh:mm:ss.fffffff tt}",date,CultureInfo.InvariantCulture);
The equivalent using string interpolation would be :
var text=FormattableString.Invariant($"{date:yyyy-MM-dd hh:mm:ss.fffffff tt}");
You should use this
string newDate = date.ToString("yyyy-MM-dd hh:mm:ss.fffffff");
More on Format specifiers here

Datetime.parseExact gives (1-9) day's value with single digit, without 0

I have this code, it gives day's value as 1,2,3 .. instead of 01,02,03..
(DateTime.ParseExact("20160416", "yyyyMMdd", CultureInfo.InvariantCulture))
gives: 4/16/2016 12:00:00 AM.
I need 04/16/2016 12:00:00 AM
I have tried different cultures but nothing worked.
DateTime doesn't store any formatting information, it's just a structure representing a date and time. ParseExact is parsing your date string correctly.
If you want it formatted, you supply a format to DateTime.ToString, for example:
var formattedDate = dateTime.ToString("MM/dd/yyyy hh:mm:ss tt");
See this fiddle.
DateTime.ParseExact returns DateTime which doesn't have any implicit format. This "format" concept only applies when you get it's textual (a.k.a. string) representation.
You didn't told use how and where you see this 4/16/2016 12:00:00 AM string but if you wanna get days part with leading zero, you can use The dd format specifier with a proper culture (for calendar and time designators).
The dd custom format string represents the day of the month as a
number from 01 through 31. A single-digit day is formatted with a
leading zero.
DateTime dt = DateTime.ParseExact("20160416", "yyyyMMdd", CultureInfo.InvariantCulture);
string str = dt.ToString("MM/dd/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture);
// 04/16/2016 12:00:00 AM

.Net DateTime.ParseExact not working [duplicate]

This question already has answers here:
How to convert datetime string in format MMMdyyyyhhmmtt to datetime object?
(2 answers)
Closed 6 years ago.
should the following parsing works,
DateTime.ParseExact("20150105 91353", "yyyyMMdd Hmmss", CultureInfo.InvariantCulture);;
I found out the above doesnt work, while the below, works,
DateTime.ParseExact("20150105 091353", "yyyyMMdd HHmmss", CultureInfo.InvariantCulture);;
I would like to know what is wrong with the first line of code.
This is one of the special cases where Custom DateTime format might find the input ambiguous.
When you do not have separator between hour and minutes, the single H format cannot distinguish the second number belongs to the hour or the minutes, thus your parse failed.
91353 //interpreted either as 9 13 53 or 91 35 3 - which one? ambiguous -> error
But this is ok:
string str = "20150105 9:13:53"; //no ambiguity with format yyyyMMdd H:mm:ss
string fmt = "yyyyMMdd H:mm:ss"; //can handle both "20150105 9:13:53" and "20150105 09:13:53"
DateTime dt = DateTime.ParseExact(str, fmt, CultureInfo.InvariantCulture);
To solve it, try to do little manipulation on your original string.
string dtstr = "20150105 91353";
string fmt = "yyyyMMdd Hmmss";
string[] parts = dtstr.Split(' ');
string str = parts[1].Length < 6 ? string.Join(" 0", parts) : dtstr;
DateTime dt = DateTime.ParseExact(str, fmt, CultureInfo.InvariantCulture);
Then it should be OK.
According to MSDN
If you do not use date or time separators in a custom format pattern, use the invariant culture for the provider parameter and the widest form of each custom format specifier. For example, if you want to specify hours in the pattern, specify the wider form, "HH", instead of the narrower form, "H".
This means this is correct DateTime.ParseExact("20150105 9:13:53", "yyyyMMdd H:mm:ss", CultureInfo.InvariantCulture); because it's using time separators

convert string in a foreign language to date

I have these input:
27 februari 2014
14 maart 2013
7 november 2013
I would like to convert them all to date field as below:
27-02-2014
14-03-2013
17-11-2013
I have tried this method: DateTime enteredDate = DateTime.Parse(s); but it does not work, the error message was:
The string was not recognized as a valid DateTime. There is a unknown
word starting at index 3.
This appears as Dutch, you can parse it by passing new CultureInfo("nl-NL") to DateTime.ParseExact like:
string str = "27 februari 2014";
DateTime dt = DateTime.ParseExact(str, "d MMMM yyyy",
new System.Globalization.CultureInfoCultureInfo("nl-NL"));
Use single d which would consider both single and double digit day part.
To get the formatted output use:
string formattedDate = dt.ToString("dd-MM-yyyy", System.Globalization.CultureInfoCultureInfo.InvariantCulture);
DateTime allows you to provide a CultureInfo, which may be enough for you. If not, and you only get one foreign language, you could simply replace the the words by the correct English ones.

Categories