Time difference calculation when values accepted in 24 hour format - c#

In C#, I am accepting 2 time values in textboxes and want to calculate the time between these 2 times. The times are accepted in 24 hour format as hhmm. There is no any semicolon or . is used in between hrs and mins.
I have tried following code :
DateTime ts1 = DateTime.Parse(TextBox3.Text);
DateTime ts2 = DateTime.Parse(TextBox4.Text);
TimeSpan ts = ts2-ts1;
TextBox12.Text = Convert.ToString(ts);
Getting the error as
String was not recognized as a valid DateTime.
Suppose TextBox3.Text = 0800 and TextBox4.Text = 2000 then TextBox12.Text = 12
Please help.

Since the format of the text in your text boxes is not the "default" date / time format the call to TimeSpan.Parse() fails / returns wrong results. (You are using a format without a colon : character for separating the hours and minutes).
In this case you'll need to specify the format explicitly, for example using the TimeSpan.ParseExact() method.
The following example parses the text "0854" into a TimeSpan value, representing the time 08:54
TimeSpan.ParseExact("0854", "hhmm", System.Globalization.CultureInfo.InvariantCulture)

You have three problems:
1) Trying to parse times as dates. Using DateTime.Parse is inappropriate here.
2) Even if you use TimeSpan.Parse, your example data does not conform to the required format for the parse method to recognise it. The accepted formats are shown here: https://msdn.microsoft.com/en-us/library/se73z7b9(v=vs.110).aspx For the time part, you would need at least to include a colon (:) between the hours and minutes in your input, e.g. 08:00.
So you can either do that, or use TimeSpan ts1 = TimeSpan.ParseExact(TextBox3.Text, "hhmm", System.Globalization.CultureInfo.InvariantCulture) in order to give it a custom format to recognise.
3) You should use the TimeSpan.Subtract method to accurately deduct one time period from the other. Currently just using - is unlikely to work, and the system will not know whether you want the output in hours, minutes, seconds or anything else.
TextBox12.Text = ts2.Subtract(ts1).Hours
Should give you what you want.
You probably ought to consider some other prior validation as well - checking that ts2 is actually greater than ts1 before allowing the input, and maybe using TryParseExact to attempt to parse the input and return true/false, in case the user has input the value incorrectly (you will get a FormatException from the Parse or ParseExact method if there's an incorrect input).

Related

How do I parse iso8601-2004 datetimes into datetime following current iso8601 standard [duplicate]

I noticed quite an interesting error when parsing some times.
DateTime fails to parse 24:00:00. Under some Googling and Stacking, I found out that DateTime only recognizes 00 - 23 (what the?????), so if your input is 24:00:00, you're out of luck. You would think someone would put in a condition to equate 24:00:00 as 00:00:00 (the midnight), but not yet..
My question is, how do I allow DateTime to allow me to parse 24:00:00?
Unfortunately I cannot to use NodaTime under specification reasons (sorry Jon. I love your library though).
Experimentation below:
An input of 2014-03-18 24:00:00 would present the following error. Expected.
An input of 2014-03-18 23:59:59 would successfully parse. Expected.
An input of 2014-03-19 00:00:00` would successfully parse. Expected.
There is no "24th hour" support in the DateTime class.
The hour (HH/H, 24-hour clock) must be 0-23, inclusive. This is why 00:00:00 is valid, but 24:00:00 is not.
Change 24:00:00 to 00:00:00 (before parsing) and, if needed, advance the day as appropriate (after parsing).
The following will work on times in the provided format (but only up to the 24th hour) although it doesn't account for an arbitrary format. Supporting different format strings only adds additional complications.
DateTime ParseWithTwentyFourthHourToNextDay (string input) {
var wrapped = Regex.Replace(input, #"24:(\d\d:\d\d)$", "00:$1");
var res = DateTime.ParseExact(wrapped, "yyyy-MM-dd HH:mm:ss", null);
return wrapped != input
? res.AddDays(1)
: res;
}
24:00:00 doesn't exist. It is 00:00:00 - 23:59:59
Why would you like to parse 24:00:00 as a valid time expression when it would be like saying 09:05:60. The roof for time is 23:59:59.99999999999 and after that, it turns over to 00:00:00.
Before parsing, do a simple search and replace - replace '24:00:00' with '00:00:00' and then parse as usual.
Convert to Minute.
if t.TotalMinutes < 0
double _24h = 0;
_24h = 1440 + t.TotalMinutes;
TimeSpan t = TimeSpan.FromMinutes(_24h);

ParseExact/TryParseExact failing with single digit hour [duplicate]

This question already has answers here:
DateTime conversion from string C#
(3 answers)
Closed 5 years ago.
I have a time and a date value with no field delimiters which I'm attempting to parse into a DateTime using TryParseExact. The time component has a single digit hour, and two digit minutes and seconds.
The following expression:
DateTime.ParseExact("20170101 84457", "yyyyMMdd Hmmss",
System.Globalization.CultureInfo.InvariantCulture)
results in FormatException with the message "String was not recognized as a valid DateTime.". I am assuming that this is because the time can't be unambiguously resolved, however since mm and ss are always going to be two digits each, I don't understand why this would be an issue.
The following results in successful parsing:
Hacking the input time to include delimiters (e.g., '8:44:57' and 'H:mm:ss')
Kludging the input time to have a leading zero if < 6 digits
Both of these seem a bit of a hack.
From what I can understand from other people's research, parsing attempts to retrieve two digits if it can, and parses from left to right.
Using my failing example of the raw time value 84857 and format Hmmss, because the hour is followed by a digit, it will be parsed as 84 - hence throwing a format exception.
According to the documentation:
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".
So it appears that if you don't have any delimiters, you are required to use HH and not H.
Personally I would pad the time component to 6 digits and use HH. The following works fine for me:
DateTime.ParseExact("20170101 084457", "yyyyMMdd hhmmss", System.Globalization.CultureInfo.InvariantCulture);
If you want to wrap this in a custom function, you can use something like this:
static DateTime ParseDateTime(string input)
{
int dateInteger, timeInteger;
var s = input.Split(' ');
bool dateOK = int.TryParse(s[0], out dateInteger);
bool timeOK = int.TryParse(s[1], out timeInteger);
if (!dateOK || !timeOK) throw new FormatException("Invalid date/time string.");
var newInput = String.Format("{0:00000000} {1:000000}", dateInteger, timeInteger);
return DateTime.ParseExact(newInput, "yyyyMMdd hhmmss", System.Globalization.CultureInfo.InvariantCulture);
}

Short Time with DateTime.ParseExact

I’m trying to parse a time. I’ve seen this question asked/answered here many times but not for this specific scenario. Here’s my code:
var time1 = DateTime.ParseExact("919", "Hmm", CultureInfo.InvariantCulture);
also
var time2 = DateTime.ParseExact("919", "Hmm", null);
both of these throw the same
"String was not recognized as a valid DateTime"
What I want is 9:19 AM.
For further info I also need to parse “1305” as 1:05 PM, this is working fine.
It seems to me I’m using the correct format. What am I overlooking?
I'm not sure there is any format that can handle this. The problem is that "H" can be either one digit or two, so if there are two digits available, it will grab both - in this case parsing it as hour 91, which is clearly invalid.
Ideally, you'd change the format to HHmm - zero-padding the value where appropriate - so "0919" would parse fine. Alternatively, use a colon in the format, to distinguish between the hours and the minutes. I don't believe there's any way of making DateTime parse a value of "919" as you want it to... so you'll need to adjust the string somehow before parsing it. (We don't have enough context to recommend a particular way of doing that.)
Yes, your format is right but since H specifier might be 2 character, ParseExact method try to parse 91 as an hour, which is an invalid hour, that's why you get FormatException in both case.
I connected to microsoft team about this situation 4 months ago. Take a look;
DateTime conversion from string C#
They suggest to use 2 digit form in your string or insert a date separator between them.
var time1 = DateTime.ParseExact("0919", "Hmm", CultureInfo.InvariantCulture);
or
var time1 = DateTime.ParseExact("9:19", "H:mm", CultureInfo.InvariantCulture);
You cant exclude the 0 prefix to the hour. This works
var time1 = DateTime.ParseExact("0919", "Hmm", CultureInfo.InvariantCulture);
Perhaps you want to just prefix 3-character times with a leading zero before parsing.
Much appreciated for all the answers. I don’t have control of the text being created so the simplest solution for me seemed to be prefixing a zero as opposed to adding a colon in the middle.
var text = "919";
var time = DateTime.ParseExact(text.PadLeft(4, '0'), "Hmm", null);

C# - Date/Time Formatting

Using C#, I am trying to format a date in to the following string format:
YYYYMMDD_HHMM.xlsx
Here is my code:
DateTime.Today.AddDays(0).ToString("yyyymmdd") + "_" + DateTime.Today.AddDays(0).ToString("hhmm")
Here is my output:
20130027_1200.xlsx
Month is not correct, nor is the time.
You're using mm, which is minutes, not months - and you're trying to print the time using DateTime.Today, which always returns midnight at the start of the day.
It's not clear why you're adding 0 days, either. I'd use:
DateTime now = DateTime.Now;
string name = now.ToString("yyyyMMdd'_'HHmm'.xlsx'");
(The ' quoting for the _ isn't strictly necessary, but personally I find it simplest to take the approach of quoting everything that isn't a format specifier.)
Or:
DateTime now = DateTime.Now;
string name = string.Format("{0:yyyyMMdd}_{0:HHmm}.xlsx", now);
Note the use of HH instead of hh to get a 24-hour clock rather than 12-hour, too.
Additionally, consider using UtcNow instead of Now, depending on your requirements. Note that around daylight saving transitions, the clock will go back or forward, so you could end up with duplicate file names.
Also note how in my code I've used DateTime.Now once - with your original code, you were finding the current date twice, which could have given different results on each invocation.
Finally, you might also want to specify CultureInfo.InvariantCulture when you format the date/time - otherwise if the current culture is one which doesn't use a Gregorian calendar by default, you may not get the results you were expecting.
DateTime.Today returns DateTime with all time-related properties set to 0. Use DateTime.Now instead.
Property value
An object that is set to today's date, with the time component set to 00:00:00.
from DateTime.Today Property
Use MM in your format to get month. mm returns minutes. You can check all format specifiers on MSDN: Custom Date and Time Format Strings

TimeSpan.Parse Parsing Issue

I am trying to parse time using TimeSpan.Parse method; However i get an unexpected result as i am trying to parse this 00:00:45.748 which supposed to be
0 Hours
0 Minutes
45 Seconds
748 Milliseconds
TimeSpan.Parse("00:00:45.748")
Result :
00:00:45.7480000
I want to know why it reads the milliseconds as 7480000 instead of 748 ?
The result you are showing is that of displaying a TimeSpan in a textual format.
By default it will show the full range.
The string you have shown actually shows that the parse was successful and you got the right result.
If you want to format the TimeSpan, use ToString with an appropriate TimeSpan format string (.NET 4.0 and above).
There are custom and standard format strings for TimeSpan.
In your case, it looks like you are looking for:
myTimeSpan.ToString("hh:mm:ss.FFF")
As additional to Oded's answer;
From TimeSpan.Parse Method (String)
ff - Optional fractional seconds, consisting of one to seven decimal
digits.
You can use The "FFF" Custom Format Specifier
Like;
TimeSpan ts = TimeSpan.Parse("00:00:45.748");
Console.WriteLine(ts.ToString(#"hh\:mm\:ss\.FFF"), CultureInfo.InvariantCulture);
Output will be;
00:00:45.748
For more informations, take a look at Standard TimeSpan Format Strings and Custom TimeSpan Format Strings
00:00:45.7480000 == 00:00:45.748
The difference is simply the number of decimal places on the milliseconds
This will format your output as desired:
var ts = TimeSpan.Parse("00:00:45.748");
Console.WriteLine(string.Format("{0:dd\\:hh\\:mm\\:ss\\.fff}", ts));
The fff is the number of decimal places you want to display (this can be from 1 to 7). See http://msdn.microsoft.com/en-us/library/ee372287.aspx
Note that this will require .NET 4.0 or above

Categories