Using C# How can I parse this string to a Time - c#

I have a C# Visual Studio web application that uses Telerik RadTimePickers to collect the start time and end times, formatted as 24 hour time. These two elements get stored in the database as a string formatted as 09:00:00-09:30:00.
Now when the application retrieves the data from the database I need to convert that string into 2 separate times, in the 24 hour format, so I can use those values as the Selected Time for the RadTimePickers.
I use the code below to extract the two dates from the string;
if (Results.TimeOfDay != "-" || Results.TimeOfDay != null)
{
string[] times = Results.TimeOfDay.Split('-');
string time1 = times[0];
RadTimePicker1.SelectedTime = ParseTime(time1);
string time2 = times[1];
RadTimePicker2.SelectedTime = ParseTime(time2);
}
The Code for ParseTime looks like this:
static public TimeSpan ParseTime(string input)
{
TimeSpan output;
var ok = TimeSpan.TryParseExact(input, #"hh\:mm\:tt", CultureInfo.InvariantCulture,out output);
return output;
}
But it is not working, the var ok value returns false and the output value is 1/1/0001 12:00:00 AM.
New to C# and cannot figure out how to fix this problem. Can someone help please
Based on comments I changed the code to parse to this
static public TimeSpan ParseTime(string input)
{
TimeSpan output;
var ok = TimeSpan.TryParseExact(input, #"hh\:mm\:tt", CultureInfo.InvariantCulture,out output);
return output;
}

if (Results.TimeOfDay != "-" || Results.TimeOfDay != null)
This will always be true, because you are asking if .TimeOfDay, or "09:00:00-09:30:00", is not equal to "-". You should use Results.TimeOfDay.Contains("-") instead.
Also,
#"h:mm tt"
This should be #"hh:mm:tt"
Edit: sorry should be #"hh\:mm\:ss"

You can just parse it as a TimeSpan with the following code
TimeSpan.TryParseExact(input, #"hh\:mm\:ss", CultureInfo.InvariantCulture, out output);
Note for TimeSpan you have to use hh rather than HH for DateTime and you have to delimit the colons.
Note you really should also check the return of TryParseExact and do something to handle when the input does not match the format. Otherwise the resulting output will be the default for TimeSpan which is 00:00:00
As other's have mentioned if (Results.TimeOfDay != "-" || Results.TimeOfDay != null) will always be true. If you change it to if (Results.TimeOfDay != "-" && Results.TimeOfDay != null) then you'll skip the parsing when TimeOfDay is null or equal to "-". Although you really should handle all the error cases which would be TimeOfDay is null, TimeOfDay does not contain a - or contains multiples and when the values on each side of the - are not formatted correctly.

Related

Date Time Format String only for Milliseconds

for a Project i parse timestamps from filenames and each has its own format. I get the files from a partner company, so the naming of the files is non negotiable. The problem now is, that besides one, every filename has a nice time format that can easily be transferred to a c# date time format string to be parsed into a DateTime object. The one that differs, strictly uses milliseconds since initialization as it's timestamp similar to
+4311123234_12345 M.txt where the numbers after the underscore are said milliseconds.
In this example the milliseconds would be 12345 but a filename could also be +4311123234_123423402345802345 M.txt where 123423402345802345 would be said milliseconds. To me only the milliseconds part is relevant and is extracted from the filename. I now want a string such as "yyyy" (for year typically) where this number is then parsed to a DateTime Object via the TryParseExact method. It is not important from when the milliseconds are counted, since it is just used for sorting so for all i care they can be the milliseconds elapsed since 01.01.1900 00:00:00.
I did a google search but came to the conclusion, that such a date time format string doesn't really exist. I know that there is ss.fffff but since i do not know how many digits the millisecond timestamp has, i would have to generate a seperate formatstring with the according number of 'f's. This is also no option, because the format string should be a user input.
Right now i coupled it to a special keyword, so that when the input is keyword the time will not be parsed by a timeformatstring but simply by the milliseconds that i got from parsing the section in the filename to a long.
It works fine, but it really isn't ideal in my opinion...
What i forgot to say was, that the string containing the timestamp is extracted from the filename via Regex CaptureGroups, so in the code example the timestampstring is in cc[0]
private static void CheckForValidMatch(SortedList<DateTime, string> files, string file, Match match,string dateTimeFormat,int groupNumber)
{
Group group = match.Groups[groupNumber];
CaptureCollection cc = group.Captures;
DateTime dateTime;
if (cc.Count == 0)
Debug.WriteLine("group did not capture anything");
else
{
if (dateTimeFormat.Equals("keyword"))
{
if (long.TryParse(cc[0].ToString(),out var result))
{
dateTime = new DateTime(result);
files.Add(dateTime, file);
}
return;
}
if (!DateTime.TryParseExact(cc[0].ToString(),dateTimeFormat,DateTimeFormatInfo.CurrentInfo,DateTimeStyles.AssumeLocal, out dateTime))
Debug.WriteLine("parsing the date time failed");
else
{
files.Add(dateTime, file);
}
}
}
Is there a way to make this more elegant, or does someone know a formatstring only for milliseconds?
Thanks in advance!
Don't expect to parse it directly as a datetime. Instead, keep a constant epoch DateTime value for the base date, parse the file name as a long, and then do this:
var FileDate = epoch.AddMilliseconds(parsedLongValue);
So we get this:
private static void CheckForValidMatch(SortedList<DateTime, string> files, string file, Match match,string dateTimeFormat,int groupNumber)
{
var cc = match.Groups[groupNumber].Captures;
if (cc.Count == 0)
{
Debug.WriteLine("group did not capture anything");
return;
}
DateTime dateTime;
if (dateTimeFormat == "keyword")
{
// I don't know your epoch date, but Jan 1, 1970 is common (it's the unix epoch)
const DateTime epoch = new DateTime(1970, 1, 1);
if (long.TryParse(cc[0].ToString(),out var result))
{
dateTime = epoch.AddMilliseconds(result);
}
else
{
Debug.WriteLine($"parsing the date time for {dateTimeormat} failed");
return;
}
}
else if (!DateTime.TryParseExact(cc[0].ToString(),dateTimeFormat,DateTimeFormatInfo.CurrentInfo,DateTimeStyles.AssumeLocal, out dateTime))
{
Debug.WriteLine("parsing the date time failed");
return;
}
files.Add(dateTime, file);
}

I have the following string "12-5" and I'm trying to parse it using TryParse in .NET. It returned true, How to acheive a false for the given string?

When giving "12-5" or "12,5" as an input to DateTime.TryParse in .NET, it is converting it to "12-05-2020" and the return value is true. How is "12-5" equal to "12-05-2020"? In my case, the input string is the user's date of birth and it is a free text as per the requirement and the parsed value "12-05-2020" makes no sense as the date of birth cant be a future date. Is there a way to correct this without using DateTime.Parse or DateTime.ParseExact as they might throw exceptions.
Well, you have 2 tests to perform:
For a valid date syntax (say, bla-bla-bla is not one)
For a valid date value (say, 25-03-2123 is not one)
Let's check for these requirements in one if:
string userInput = "12-05-15"; // 12 May 2015
...
// We can use several formats in one go:
// DateTime.TryParseExact will try formats in the given order
string[] allowedFormats = new string[] {
"d-M-yy", "d-M-yyyy", "MMM d yyyy",
};
if (DateTime.TryParseExact(
userInput.Trim(), // let's tolerate leading/trailing whitespaces
allowedFormats,
CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out var result) &&
result <= DateTime.Today &&
result >= DateTime.Today.AddYears(-150)) {
// result is
// 1. Valid date
// 2. At least 150 years ago
// 3. At most today
}
else {
// userInput doesn't meet at least one criterium
}
As #Rafalon suggested, use DateTime.TryParseExact to avoid exceptions and set the format you want.
string dateformat = "12-05";
bool answer = DateTime.TryParseExact(dateformat, "dd-MM-yyyy", CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime result);

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.

Ensuring correct input is given for 24 hour time format

I'm currently trying to make a program that asks the user to input time in a 24 hour format (hh:mm). i then put it into a string and .split(':') it to seperate the hours and minutes and then make it one big integer. such as: user inputs "18:40" i then interpret it as 1840 and find a value for it in an array (I'm working on a transportation timetable). what I'm having immense trouble with is making sure the user has a valid input and asking the user to try again if: 99:50 or 12:80 is input. but extremely confused because i also have to check with the array to throw back an error message if the user tries to arrive to early. sorry for the poor wording.
This is how I did it in c#:
bool validTime(string time) {
return TimeSpan.TryParse(time, out TimeSpan t);
}
You could split the string and convert then separately to integers. Validate each if they are within a range. Don't concat the hours and minutes. If you want 1 integer number, you might want it as minutes. (hours * 60) + minutes
You should use the DateTime.TryParse() for this. Because it's a better way.
If you just want to check if the user input is in a valid range, as you asked, just split the string as you did. Parce the parts in an int and validate the parts.
public bool CheckUserInput(string ui)
{
string[] parts = ui.Split(':');
if (parts.Count()==2)
{
int hour = int.Parse(parts[0]);
int mins = int.Parse(parts[1]);
if (hour >= 0 && hour < 24 && mins >= 0 && mins < 60)
return true;
}
return false;
}
Parse the string as DateTime, and then work with it. Also, it would be better to store the time in an appropriate format in the database, e.g. as time.
string input = "18:40";
DateTime time;
var ok = DateTime.TryParse(input, out time);
if (ok) {
var timeString = string.Format("{0:00}{1:00}", time.Hour, time.Minute);
}
else {
throw new ArgumentException($"Invalid input, expected time in format HH:MM. Actual input was '{input}'.", nameof(input));
}
Edit: use format string with leading zeros

How can a string timestamp with hours 0 to 24 be parsed

I am trying to parse a string timestamp of format "yyyyMMddHHmmss" with DateTime.ParseExact(). The catch is I must allow for an hour value of "24" (i.e. hours can be from 0 to 24, where hour 24 denotes hour 0 of the next day (day + 1, hour = 0) Note: I can't control the input values.) and, of course, that results in an exception.
Are there any settings/properties I can set instead of manually parsing/using regex's? If not, any efficient parsing ideas?
ex.
DateTime.ParseExact("20120911240000", "yyyyMMddHHmmss",
System.Globalization.CultureInfo.InvariantCulture);
if you want to do it manually you can use String.Substring() to detect hour values of "24", then use String.Replace, to set that to "00", then parse your date, and then add a day if that's what an hours value of "24" means
Sam's solution is good, but since you are using yyyyMMddHHmmss I would do something like:
bool addDay = false;
DateTime result;
string dtToParse = "20120911240000";
if (dtToParse[8] == '2' && dtToParse[9] == '4')
{
dtToParse = dtToParse.Substring(0, 8) + "00" + dtToParse.Substring(10);
addDay = true;
}
result = DateTime.ParseExact(dtToParse, "yyyyMMddHHmmss", System.Globalization.CultureInfo.InvariantCulture);
if (addDay) { result = result.AddDays(1); }
There is no simple flag to do what you want.
However, here is the way to create custom datetime parser:
How to create and use a custom IFormatProvider for DateTime?

Categories

Resources