DateTime.TryParseExact method for string comparison - c#

Hey how can you do a string comparison match for a given date, DateTime.TryParseExact seems like the sensible option but I am not sure how to construct the arguement in the below method:
public List<Dates> DateEqualToThisDate(string dateentered)
{
List<Dates> date = dates.Where(
n => string.Equals(n.DateAdded,
dateentered,
StringComparison.CurrentCultureIgnoreCase)).ToList();
return hiredate;
}

If you know the format of the date/time exactly (i.e. it never changes, and does not depend on the culture or locale of the user), then you can use DateTime.TryParseExact.
For example:
DateTime result;
if (DateTime.TryParseExact(
str, // The string you want to parse
"dd-MM-yyyy", // The format of the string you want to parse.
CultureInfo.InvariantCulture, // The culture that was used
// to create the date/time notation
DateTimeStyles.None, // Extra flags that control what assumptions
// the parser can make, and where whitespace
// may occur that is ignored.
out result)) // Where the parsed result is stored.
{
// Only when the method returns true did the parsing succeed.
// Therefore it is in an if-statement and at this point
// 'result' contains a valid DateTime.
}
The format string can be a fully specified custom date/time format (such as dd-MM-yyyy), or a general format specifier (such as g). For the latter, the culture matters as to how the date is formatted. For example, in the Netherlands dates are written as 26-07-2012 (dd-MM-yyyy) whereas in the US dates are written as 7/26/2012 (M/d/yyyy).
However, this all only works when your string str contains only the date you want to parse. If you have a bigger string with all sorts of unwanted characters around the date, then you'll have to find the date in there first. This can be done using a regular expression, which is a whole other topic in itself. Some general information about regular expressions (regex) in C# can be found here. A regular expression reference is here. For example, a date similar to d/M/yyyy can be found using the regex \d{1,2}\/\d{1,2}\/\d{4}.

Another way of doing it is to convert your date from string to DateTime. If it is possible I would keep DateAdded as DateTime.
Bellow is a code that runs in LINQPad
public class Dates
{
public string DateAdded { get; set; }
}
List<Dates> dates = new List<Dates> {new Dates {DateAdded = "7/24/2012"}, new Dates {DateAdded = "7/25/2012"}};
void Main()
{
DateEqualToThisDate("7/25/2012").Dump();
}
public List<Dates> DateEqualToThisDate(string anything)
{
var dateToCompare = DateTime.Parse(anything);
List<Dates> hireDates = dates.Where(n => DateTime.Parse(n.DateAdded) == dateToCompare).ToList();
return hireDates;
}

Related

How to parse a timespan in order to add it to a datetime?

I've got a string in the following format: 05/06/2019|1330|60
The output I'm looking for is: 05/06/2019T14:30:00
I'm attempting to parse out the TimeSpan portion right now:
public static string getProcedureEndingDateTime (string input) {
//05/06/2019|1330|60
string myDate = input.Split ( '|' ) [0];
DateTime myDateTime = DateTime.Parse (myDate);
string myTime = input.Split('|')[1];
string hours = myTime.Substring(0,2);
string minutes = myTime.Substring(2,2);
TimeSpan myTimeSpan = TimeSpan.Parse($"{hours}:{minutes}");
myDateTime.Add(myTimeSpan);
return myDateTime.ToString();
}
But right now, getting the following output:
To get the above output I'm calling my function like so:
Console.WriteLine (getProcedureEndingDateTime("05/06/2019|1330|60"));
How do I parse the string "1330" into a TimeSpan?
No need to us a Timespan here, just call ParseExact instead with a proper format to do it in one line.
var myDateTime = DateTime.ParseExact("05/06/2019|1330|60", "dd/MM/yyyy|HHmm|60", CultureInfo.InvariantCulture);
Console.WriteLine(myDateTime.ToString());
//this gives 2019-06-05 1:30:00 PM, format depends on your PC's locale
I don't know what the 60 part is, you can adjust the format or substring it out beforehand.
The problem is because Add() returns a new DateTime instance, which means you're currently discarding it. Store it, and return that from your function instead, like so:
var adjusted = myDateTime.Add(myTimeSpan);
return adjusted.ToString();
Try using the numeric values as exactly that, numbers.
Also, the other issue with your code is the DateTime.Add() method doesn't add to that DateTime variable. Instead it returns a new variable, which you are ignoring.
Try this:
public static string getProcedureEndingDateTime (string input) {
string[] parts = input.Split('|');
string myDate = parts[0];
DateTime myDateTime = DateTime.Parse (myDate);
string myTime = parts[1];
if (!int.TryParse(myTime.Substring(0,2), out int hours))
hours = 0;
if (!int.TryParse(myTime.Substring(2,2), out int minutes))
minutes = 0;
TimeSpan myTimeSpan = new TimeSpan(hours, minutes, 0);
myDateTime += myTimeSpan;
return myDateTime.ToString();
}
Assuming the date shown is May 6th (and not June 5th), and also assuming the 60 represents a time zone offset expressed in minutes west of GMT, and also assuming you want the corresponding UTC value, then:
public static string getProcedureEndingDateTime (string input) {
// example input: "05/06/2019|1330|60"
// separate the offset from the rest of the string
string dateTimeString = input.Substring(0, 15);
string offsetString = input.Substring(16);
// parse the DateTime as given, and parse the offset separately, inverting the sign
DateTime dt = DateTime.ParseExact(dateTimeString, "MM/dd/yyyy|HHmm", CultureInfo.InvariantCulture);
TimeSpan offset = TimeSpan.FromMinutes(-int.Parse(offsetString));
// create a DateTimeOffset from these two components
DateTimeOffset dto = new DateTimeOffset(dt, offset);
// Convert to UTC and return a string in the desired format
DateTime utcDateTime = dto.UtcDateTime;
return utcDateTime.ToString("MM/dd/yyyy'T'HH:mm:ss", CultureInfo.InvariantCulture);
}
A few additional points:
Not only is the input format strange, but so is your desired output format. It is strange to see a T separating the date and time and also see the date in the 05/06/2019 format. T almost always means to use ISO 8601, which requires year-month-day ordering and hyphen separators. I'd suggest either dropping the T if you want a locale-specific format, or keep the T and use the standard format. Don't do both.
In ISO 8601, it's also a good idea to append a Z to UTC-based values. For DateTime values, the K specifier should be used for that. In other words, you probably want the last line above to be:
return utcDateTime.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// outputs: "2019-05-06T14:30:00Z"
You might want to not format a string here, but instead return the DateTime or DateTimeOffset value. It's usually better to create a string only at the time of display.
Don't forget that the DateTime struct is immutable. In your question you were ignoring the return value of the Add method.

How to parse a Date and Time, separately, into a DateTime in C#?

I'm trying to parse two separate fields, a date and a time, into one DateTime object as strings. The date has padding, the time doesn't, but they follow a consistent format, with date being something like 07302018 and time being 101230; an issue being, as well, that time could be something like 91230. What I've tried right now:
string timeformat1 = "MMddyyyy HHmmss";
string timeformat2 = "MMddyyyy Hmmss";
string date = "07302018"
string time = "63020"
if (time.Length == 6)
{
datetimeobject = DateTime.ParseExact($"{date} {time}", timeformat1, CultureInfo.InvariantCulture);
}
else
{
datetimeobject = DateTime.ParseExact($"{date} {time}", timeformat2, CultureInfo.InvariantCulture);
}
Doesn't seem to work, giving a "String was not recognized as a valid DateTime" exception.
Am I going to need to insert some slashes and punctuation into the strings in order to make them read correctly? I wanted to avoid this because I had heard there are performance concerns with disassembling and reassembling strings, but I may have to do so unless there is a more elegant solution.
Try this to avoid ifs
string timeformat = "MMddyyyy HHmmss";
string date = "07302018";
string time = "91230";
string joint = $"{date} {time.PadLeft(6,'0')}";
DateTime datetimeobject = DateTime.ParseExact(joint, timeformat, System.Globalization.CultureInfo.InvariantCulture);
The DateTime.ParseExact will fail with a single char for hour and the single H because it need a separation between hour and other values. From MSDN:
If format is a custom format pattern that does not include date or
time separators (such as "yyyyMMddHHmm"), 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 format
pattern, specify the wider form, "HH", instead of the narrower form,
"H".

How to get the desired output by modifying string after removing / from string

I have a string like this:
30/04/2018 o/p=300418
01/03/2017 o/p=010317
10/11/2018 o/p=101118
12/11/2123 o/p=121123
1/1/2018 o/p =010118
code tried but can't get the last one 1/1/2018
string a = "31/04/2018";
string b = a.Replace("/","");
b = b.Remove(4, 2);
You should parse to a DateTime and then use the ToString to go back to a string. The following works with your given input.
var dateStrings = new []{"30/04/2018", "01/03/2017","10/11/2018","12/11/2123","1/1/2018"};
foreach(var ds in dateStrings)
{
Console.WriteLine(DateTime.ParseExact(ds, "d/M/yyyy", System.Globalization.CultureInfo.InvariantCulture).ToString("ddMMyy"));
}
The only change I made is to the first date as that is not a valid date within that month (April has 30 days, not 31). If that is going to be a problem then you should change it to TryParse instead, currently I assumed your example was faulty and not your actual data.
Your structure varies, all of the examples above use two digit month and day, while the bottom only uses a single digit month and day. Your current code basically will replace the slash with an empty string, but when you remove index four to two your output would deviate.
The simplest approach would be:
var date = DateTime.Parse("...");
var filter = $"o/p = {date:MMddyyyy}";
Obviously you may have to validate and ensure accuracy of your date conversion, but I don't know how your applications works.
If you can reasonably expect that the passed in dates are actual dates (hint: there are only 30 days in April) you should make a function that parses the string into DateTimes, then uses string formats to get the output how you want:
public static string ToDateTimeFormat(string input)
{
DateTime output;
if(DateTime.TryParse(input, out output))
{
return output.ToString("MMddyy");
}
return input; //parse fails, return original input
}
My example will still take "bad" dates, but it will not throw an exception like some of the other answers given here (TryParse() vs Parse()).
There is obviously a small bit of overhead with parsing but its negligible compared to all the logic you would need to get the proper string manipulation.
Fiddle here
Parse the string as DateTime. Then run ToString with the format you desire.
var a = "1/1/2018";
var date = DateTime.Parse(a);
var result = date.ToString("ddMMyyyy");
You can use ParseExact to parse the input, then use ToString to format the output.
For example:
private static void Main()
{
var testData = new List<string>
{
"31/04/2018",
"01/03/2017",
"10/11/2018",
"12/11/2123",
"1/1/2018",
};
foreach (var data in testData)
{
Console.WriteLine(DateTime.ParseExact(data, "d/m/yyyy", null).ToString("ddmmyy"));
}
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
You didn't specify whether these are DateTime values or just strings that look like date time values. I'll assume these are DateTime values.
Convert the string to a DateTime. Then use a string formatter. It's important to specify the culture. In this case dd/mm/yyyy is common in the UK.
var culture = new CultureInfo("en-GB");//UK uses the datetime format dd/MM/yyyy
var dates = new List<string>{"30/04/2018", "01/03/2017","10/11/2018","12/11/2123","1/1/2018"};
foreach (var date in dates)
{
//TODO: Do something with these values
DateTime.Parse(date, culture).ToString("ddMMyyyy");
}
Otherwise, running DateTime.Parse on a machine with a different culture could result in a FormatException. Parsing dates and times in .NET.

Convert dd/MM/yyyy to yyyy/MM/dd?

I want to convert a string '30/12/2012' to '2012/12/30'. My application is set to "en-CA" however the database accepts yyyy/MM/dd as default.
How can I do this without depending on the current culture info set
at server?
As all the comments have said, but none of the answers have said so far: don't pass this to the database as a string.
Parse any text you receive as early as possible, then use DateTime to represent it everywhere else, including how you send it to the database, via parameterized SQL1. This goes for values of all kinds: convert it into the "natural" type for the data as soon as possible, and keep it in that natural representation for as long as possible. A date isn't a string, and you should only convert it to a string if you really, really need to - ideally just before displaying it to a user.
The parsing can be done with DateTime.ParseExact or DateTime.TryParseExact depending on whether this is "suspicious" data (e.g. from a user) or data which should really be correct and for which an exception is the most appropriate reaction to unparseable values. I suggest you pass in CultureInfo.InvariantCulture with your custom format string. For example:
DateTime date = DateTime.ParseExact(text, "dd/MM/yyyy",
CultureInfo.InvariantCulture);
(If you do a lot of date/time work, you may also want to consider using my Noda Time project which allows you to express the value in a richer way - in this case you'd probably use LocalDate.)
1 If you're not already using parameterized SQL, but are instead baking values directly into the SQL, you have bigger problems than date/time conversions.
You can specify CultureInfo in Format and most ToString functions.
I.e. DateTime.ToString(CultureInfo) and DateTime.Parse(string, CultureInfo) will let you pars string in one culture (i.e. current or new CultureInfo("en-CA")) and format with another like new CultureInfo("en-us").
Note: you may consider running all DB access under some other culture (i.e. en-US) by setting Thread.CurrentCulture as sometimes number fomats are also impacted (if numbers are storead as string).
If its going to always be in the same format. Then split it on the / character
string[] tempsplit = datestring.Split('/');
and then put it back together
string joinstring = "/";
string newdate = tempsplit[2] + joinstring + tempsplit[1] + joinstring + tempsplit[0];
simple.
First convert your string to DateTime format using
DateTime dt = Convert.ToDateTime("your string value");
Then save it in string using:
string st=dt.ToString("yyyy/MM/dd");
This will convert your date format to any desired format you want without depending on culture
Without going into the issue what format the database accepts or not, you can do the conversion like this:
Convert the String to Datetime like explained here
Change the format and convert it to string again like this
This seems to work.
var x = new string[] { "2012/06/12", "20/06/2012", "111/111/1111" };
foreach (var ds in x)
{
DateTime d = default(DateTime);
try
{
d = DateTime.Parse(ds, CultureInfo.GetCultureInfo("en-CA"));
}
catch (Exception ex)
{
try
{
d = DateTime.ParseExact(ds, "yyyy/MM/dd", CultureInfo.InvariantCulture);
}
catch
{
}
}
if (d == default(DateTime))
Console.WriteLine("error");
else
Console.WriteLine(d.ToString());
}

Is there a way to compare date "strings" in C# without converting the strings?

I have two fields:
string date1 = "04/26/10";
string date2 = "04/25/10";
How can I compare these two fields like so?:
if (date2 <= date1)
{
// perform some code here
}
Can this be done without first converting the fields to a separate date-type variable?
EDIT: I should mention that these values are coming from a database table where the date values are in a string format to begin with. Old legacy code...
No, but it is not difficult to convert to a date in C#.
if ( DateTime.Parse(date2,CultureInfo.InvariantCulture) <= DateTime.Parse(date1,CultureInfo.InvariantCulture))
{
// perform some code here
}
CultureInfo depends on the format the string dates have in the legacy DB. See: DateTime formats used in InvariantCulture
If your dates are actually stored as strings in the database, it seems like you can't be sure they'll be in a valid format before parsing. For that reason I'd suggest a small variation on jle's answer:
DateTime d1, d2;
if (DateTime.TryParse(date1, out d1) &&
DateTime.TryParse(date2, out d2) &&
d2 <= d1)
{
// perform some code here
}
else
{
// strings didn't parse, but hey,
//at least you didn't throw an exception!
}
At the very least you need to pick apart the strings in order to compare them in the right order.
If you want to leave them as strings, then you need to reorder them with LARGEST->SMALLEST units, so this:
yyyy/mm/dd
can be compared directly, but not the format you have. With your format, you need to split it, and either recombine it like above, or compare the individual pieces in the right order.
Having said that, it is rather easy to convert the strings to DateTime using DateTime.ParseExact.
Generally it is a bad idea to compare date as strings.
But if your strings are in the same format (e.g. yyyy/mm/dd means years, then monthes then days) then the comparison may be valid.
It could be done with string manipulation, but it would come down to effectively comparing three sets of integers, which as strings would induce more overhead than converting to datetimes. Why would you want to do that?
No. Let the .net framework sort that out for you. It will correctly identify the user date settings and format (using system settings, current thread) and determine which is the month, year and day - especially if that data comes from eg a sql server.
It's preferred to have the date formatted before doing the comparison. Depending in your cultureinfo, the safest way to compare dates is to format the date string to "yyyy-mm-dd".
DateTime d1, d2;
string date1 = "04/26/10";
string date2 = "04/25/10";
d1 = DateTime.Parse(date1.ToString("yyyy-MM-dd"));
d2 = DateTime.Parse(date2.ToString("yyyy-MM-dd"));
if (d1 > d2)
{
//do something
}
Best practice is to avoid comparing date as string types and compare with the official DateTime object of C#.
If your use-case requires the comparison using string objects then:
1st, make sure the date string format is yyyymmdd as recommend by Lasse V. Karlsen.
2nd, use the string method CompareTo to compare between the dates.
Here's how the method works in your case (Used C# Online Compiler to test this):
using System;
public class Program
{
public static void Main()
{
string fmt = "yyyymmdd";
string min = "20201206";
string max = "20210810";
Console.WriteLine(max.CompareTo(min)); // Output : 1
Console.WriteLine(min.CompareTo(max)); // Output : -1
string same1 = "20001212";
string same2 = "20001212";
Console.WriteLine(same1.CompareTo(same2)); // Output : 0
Console.WriteLine(same2.CompareTo(same1)); // Output : 0
// Summary:
// 1 = Greater than string param
// -1 = lesser than string param
// 0 = equals to string param
}
}

Categories

Resources