Using the below DateTime.TryPaseExact method gives me different out puts when one is expected.
I get the following formats returned from the code below:
2014-02-10 18:32:37
1402-10-18 17:23:00 (which is clearly incorrect)
How do I just get a yyyy-MM-dd HH:mm:ss format returned?
static readonly string[] DateFormats = new string[] { "yyMMddHHmm", "yyyyMMddHHmm", "yyMMddHHmmss", "yyyy-MM-dd HH:mm:ss" };
DateTime date;
DateTime.TryParseExact("140211090915", DateFormats, CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal, out date);
Also if someone could explain why this 140211084947 input returns the expected format and 140211090915 returns an unwanted format I would be grateful
It is clear that you are mistaken.
When the format is yyMMddHHmmss, it is taking first 2 digits as a year which in this case is 14 and is automatically converted to 2014.
When format is something like yyyy...., it is taking first 4 digits as a year which in your case is 1402.
From The "yy" Custom Format Specifier
In a parsing operation, a two-digit year that is parsed using the "yy"
custom format specifier is interpreted based on the
Calendar.TwoDigitYearMax property of the format provider's current
calendar.
From Calendar.TwoDigitYearMax property
This property allows a 2-digit year to be properly translated to a
4-digit year. For example, if this property is set to 2029, the
100-year range is from 1930 to 2029. Therefore, a 2-digit value of 30
is interpreted as 1930, while a 2-digit value of 29 is interpreted as
2029.
As Marcin mentioned, your string input doesn't match with yyMMddHHmm and yyyy-MM-dd HH:mm:ss formats.
Your 140211084947 string matches with yyMMddHHmmss format but it doesn't match with yyyyMMddHHmm format (Because 49 is not a valid hour)
Related
var date= DateTime.ParseExact("16-03-2022 1:30", "dd-MM-yyyy HH:mm", CultureInfo.InvariantCulture);
When I enter 16-03-2022 13:30, it does not give an error but when the parameter is 16-03-2022 1:30, I get an error, how can I solve it?
I feel like taking a risk to answer but..
Let's go step by step. One of the good things about .NET methods is that you can see what exceptions can be thrown on that method in their documentation.
From "Exception" section on documentation it says;
FormatException
s or format is an empty string.
-or-
s does not contain a date and time that corresponds to the pattern
specified in format.
-or-
The hour component and the AM/PM designator in s do not agree.
Your s or format is not empty, your string does not have any AM or PM designator, so the only option left is "s does not contain a date and time that corresponds to the pattern specified in format." as a reason.
Also from documentation, it says;
Converts the specified string representation of a date and time to its
DateTime equivalent using the specified format and culture-specific
format information. The format of the string representation must match
the specified format exactly.
What "format" we are talking about? There are two of them. Custom date and time format strings and Standard date and time format strings. Since we are using DateTime.ParseExact, we need to consider using custom date and time format.
Let's look at all parts can be parse in your 16-03-2022 1:30 string;
16 --> Two digit day number (dd)
03 --> Two digit month number with leading zero (MM)
2022 --> Four digit year (yyyy)
1 --> One digit hour (it can be h or H because there is no time designator in your string and we can't know it's in 12-hour clock format or 24-hour clock format)
30 --> Two digit minutes (mm)
So, the proper format of your 16-03-2022 1:30 string can be either dd-MM-yyyy H:mm or dd-MM-yyyy h:mm which depends on you. If it is 24-hour format, use H specifier, if it is 12-hour format, use h specifier.
When you see the word "Exact" in ParseExact(), it means it. Any deviation from the expected format at all will cause an exception.
In this case, the HH specifier is not an exact match for the 1 value for the hour. It would match if you had 01 instead, but just 1 isn't the same thing. To match the hours without leading zeros you need a single H, creating this format string:
dd-MM-yyyy H:mm
This will still match later hours like "10" and "11". Additionally, the capital "H" instead of lower-case means it still expects 24-hour time, so numbers like "13" up to "23" still work, too.
If you could get a mix of values, that sometimes has just the 1 and sometimes might have the full 01, then you need to use a ParseExact() overload that accepts an array of formats, and provide both versions.
I have a program that do several things.
Two of them is read a date from a txt and rewrite a date in the same txt.
The read of the date is a regex expression like:
[0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-5]{1}[0-9]{1})
The problem is that my regex expression only works in the format
"DD/MM/YYYY hh:mm:ss" and its impossible to make sure my regex expression can match all system datetime formats.
So, I need to make sure my program run's in every system, regardless the system datetime.now.
For that, i thought about format every system datetime.now, at start, to the format mentioned "DD/MM/YYYY hh:mm:ss".
At the moment i have the following code:
Datetime currentDate = DateTime.ParseExact(DateTime.Now.ToString(), "DD/MM/YYYY hh:mm:ss", CultureInfo.InvariantCulture);
However, when running some tests, using a system date in format "D/M/YYYY h:m:s" i get the error:
"String was not recognized as a valid DateTime."
The problem is that if my date, for example, is "9/27/2019 04:26:46"(M/D/YYYY h:m:s) it can't fit in the format i defined.
Any idea?
Thank you in advance!
You need to use the same format string and culture in every place where you convert the DateTime to string as well. In your sample code, you're doing
DateTime.Now.ToString()
This uses the default culture for the thread, and the default format. Unless assigned otherwise, the thread is probably using the local culture info. Instead, you would want to use the same format and the invariant culture:
DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
(note the lowercase "dd". "DD" is not a valid format specifier for date times; these things are case sensitive. Also note the "HH", which gives a 24-hour value, rather than 12-hour)
In practice, just using the invariant culture should be enough for persistence. Cultures already include default datetime formats, so unless you have a specific need to use a different format, why not use the default?
Also note that DateTime doesn't have a format. The format only comes into play when you convert from or to a string. That is the place where you need to ensure the same culture and format is used for both sides of the operation (and that's why for persistence, especially for data shared between different users or computers, you generally want to use the invariant culture).
If you need
to make sure my program run's in every system, regardless the system datetime.now
you can adapt international standard for this, say, ISO 8601.
In order to validate the DateTime, regular expressions like you have are not enough (just imagine leap years), but TryParse does it job:
string source = "2019-09-26T23:45:59";
// Either current culture date and time format or ISO
bool isValid = DateTime.TryParse(
source,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out var _date);
Or if you want to be more restrictive use TryParseExact:
// ISO only
bool isValid = DateTime.TryParseExact(
source,
"s",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out var _date);
If you want to represent DateTime.Now in ISO 8601, add "s" standard format string:
string dateAsString = DateTime.Now.ToString("s");
Alas, you can provide a bunch of formats which are able to cope with any date and time formats; a classical example of ambiguous date is
01/02/03 - 01 Feb 2003 (Russia)
01/02/03 - 02 Jan 2003 (USA)
01/02/03 - 03 Feb 2001 (China)
You can alleviate the problem, while providing several formats:
// Here we try to support 4 formats (note different delimeters)
string[] formats = new string[] {
"s", // try ISO first
"dd'.'MM'.'yyyy HH':'mm':'ss", // if failed try Russian
"MM'/'dd'/'yyyy HH':'mm':'ss", // on error have a look at USA
"yyyy'-'MM'-'dd HH':'mm':'ss", // the last hope is Chinese
};
bool isValid = DateTime.TryParse(
source,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out var date);
I thought this would be easy:
I want to parse the following string format to DateTime:
"4/25/18 3:11 PM"
and it's a lot more difficult than I expected.
DateTime.Parse just returns an exception Input string not in the correct format
DateTime.TryParseExact is the closest I have come, and it can parse this exact string, but it does not account for when day, month, hour (etc) goes over (or below, depending on the mask) 9 since the mask has to match exactly or it will fail.
string input = "4/25/18 3:11 PM";
string input2 = "1/1/18 10:10 AM";
DateTime theDate;
DateTime.TryParseExact(input, "M/dd/yy h:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out theDate);
My next idea was to split out the 4, 25, 18 and add a 0 if they are < 10, and a 20 concatenated before the 18 but this seems overkill. It also leaves me with the time and making conditions based on if the tt is AM or PM.
EDIT: Based on some comments....
I have no control over the input string.
Convert.ToDateTime("25/4/18 3:11 PM") throws an exception {"String was not recognized as a valid DateTime."}
When I specified the input date as 4/25/18, the input format is clearly M/dd/yy. Unfortunately this can mean the input date can be MM/d/yy etc. We can assume it will always be Month / Day / Year..
TLDR: How can I parse input and input2 to a DateTime cleanly?
Thanks
You can change your code to be like this, and then it should accept both formats with single and double digits:
DateTime.TryParseExact(
input, "M/d/yy h:mm tt",CultureInfo.InvariantCulture, DateTimeStyles.None,
out var theDate);
The single character M, d,and h components in the format string allow for single or double digits.
Fiddle
If the code is executed in US Locale and the date string is known or expected to be a valid US date format:
Convert.ToDateTime("4/25/18 3:11 PM")
For other locales (assuming the input string is valid in the current culture) try this overload:
Convert.ToDateTime("25/4/18 3:11 PM", System.Globalization.CultureInfo.CurrentCulture)
However, based on your revision and comments if I understand correctly, you expect the date will always be in M/D/Y (US) format:
I have no control over the input string.
Convert.ToDateTime("25/4/18 3:11 PM") throws an exception {"String was not recognized as a valid DateTime."}
When I specified the input date as 4/25/18, the input format is clearly M/dd/yy. Unfortunately this can mean the input date can be MM/d/yy etc. We can assume it will always be Month / Day / Year.
Sure. In that case you're attempting to execute against an invalid US date, on a US culture. But if you can assume the date format provided in string will always be month/day/year, then you should be able to do:
Convert.ToDateTime("4/25/18 3:11 PM", new System.Globalization.CultureInfo("en-US"))
This seems to work whether month/day are provided in single or double-digit, and should return valid DateTime object based on assumed en-US date string.
In a .Net application, I would like to format a date and time in a fixed length format, but with no leading zeros for the day as below:
String.Format("{0:d MMM HH:mm:ss}", DateTime.Now);
"25 Jun 04:21:11"
This works for days of the month greater than ten, but (as documented) does not insert a leading space. Now, the following should provide the format required:
String.Format("{0,2:d}", DateTime.Now);
"25/06/2016"
but, as is seen, formats the date instead using the standard Short date format string. I can use:
String.Format("{0,2:''d} {0:MMM HH:mm:ss}", DateTime.Now.AddDays(-20));
" 5 Jun 04:21:11"
to get the desired effect, but this does not seem very satisfactory.
Is there less of a workaround to have the formatter use the Custom format string interpretation of an isolated d instead of the Short date Standard format?
To distinguish between a custom and standard format when the format is only a single character, use the % symbol. For example: {0:d} gives the standard date format, but {0:%d} gives just the day of the month. See the MSDN docs for more details.
So, you could do this:
String.Format("{0,2:%d} {0:MMM HH:mm:ss}", ...
However, consider that you could also just specify the length of the entire string:
String.Format("{0,15:d MMM HH:mm:ss}", ...
Of course, this assumes that MMM will always be three characters long. That is true for English (as .NET uses "Sep" instead of "Sept"), but isn't guaranteed for all languages and locales.
Also note that you should use HH for 24 hour time. hh gives 12 hour time, but is meaningless without using tt to indicate the meridem designation (am/pm).
I tried converting 9/29/2013 2:44:28 PM (mm/dd/yyyy) to dd/mm/yyyy format.
I got a strange Date after Converting.
I tried
dateTimeVar.ToString("dd/mm/yyyy");
29/44/2013
The Date was a type of DateTime itself.
Lowercase mm means minutes, try this instead:
dateTimeVar.ToString("dd/MM/yyyy");
However, if this works depends on your local culture. If your current culture's date separator is different, / will be replaced with that. So if you want to enforce it use CultureInfo.InvariantCulture:
dateTimeVar.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
MM is for months, mm is for minutes. That's why it gets your minutes (which is 44) instead of your month value.
Use it like;
dateTimeVar.ToString("dd/MM/yyyy");
Check out;
The "MM" Custom Format Specifier
The "mm" Custom Format Specifier
And remember, / has special meaning when you use it as a date separator. It replace itself with your current culture date separator. Forcing to use with InvariantCulture would be better.
dateTimeVar.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
Take a look at;
The "/" Custom Format Specifier
What if I want to convert a string in dd/MM/yyyy to DateTime?
Then you can use DateTime.ParseExact method.
Converts the specified string representation of a date and time to its
DateTime equivalent using the specified format and culture-specific
format information. The format of the string representation must match
the specified format exactly.
As an example;
string s = "01/01/2013";
DateTime dt = DateTime.ParseExact(s, "dd/MM/yyyy", CultureInfo.InvariantCulture);
Console.WriteLine(dt);
Output will be;
1/1/2013 12:00:00 AM
Here a DEMO.
dateTimeVar.ToString("dd/mm/yyyy"); // Change to dd/MM/yyyy
The problem is mm stands for minute and you need MM which would be months
Tim's answer is correct, but to remove the format string altogether you can use. 'ToShortDateString'
DateTime date = DateTime.Today;
var stringDate = date.ToShortDateString();
var stringDate2 = date.ToString("dd/MM/yyyy");