C# seconds in string format to TimeSpan - c#

I'm having a bit of a issue with this.
What I want to do is take this string 27.0 and convert it to a timespan.
I tried every way I could think of in order to get it to work.
TimeSpan.Parse("27.0") I know it's a format issue but I'm not sure of the format to use.
I basically have 4 values
27.0
52.4
1:24.4
1:43.3
Is there a easy way to handle all these formats?
Thanks!
Sorry these are all seconds except the 1 is minute so 1 minute 24 seconds 4 milliseconds

You can use two different approaches. Use one of the TimeSpan.From...() methods. Those convert numbers to a TimeSpan. For example to convert the double 27 to a TimeSpan with 27 seconds you use
var ts = TimeSpan.FromSeconds(27)
The only problem you will face here is that it does not allow you to specify a string. So you could for example first parse your string as an double. If you do it naivly just like that, it can be you get what you wanted, or not.
var ts = TimeSpan.FromSeconds(double.Parse("27.0"))
But if you run this for example on a system with a German locale you will get a TimeSpan with 4 minutes and 30 seconds. The reason for that is that a dot in German is not a divider for a number, it is the thousand seperator. So that number is parsed as "270". So to be safe you should also provide a NumberFormat. A better way would be.
var culture = new CultureInfo("en-US");
var tsc = TimeSpan.FromSeconds(double.Parse("27.0", culture.NumberFormat));
Now you get your 27 seconds. But the problem is still that it only parses your two first strings correctly. Your other 3 strings will still not parse, because you can't convert them to numbers. But I still added this, to be aware of culture difference if you just go up and try to parse a number to an double und use TimeSpan.FromSeconds() and so on.
Now lets look further how you can parse every string. There exists TimeSpan.Parse() and TimeSpan.ParseExact().
Now you still must knew that TimeSpan.Parse() uses culture specific formatting. In a country where a time is not separated with colons a TimeSpan.Parse() will fail. On Top of that, TimeSpan assumes a format "hh:mm" at minimum. But the Colon in this format is culture-sensitive. You could use the "en-US" Culture once again, but it wouldn't solve the problem because he doesn't accept the format "27.0".
That is the reason why you must use the TimeSpan.ParseExact() method and and provide the formats that this method should be able to parse. It also allows you to specify formats that he should be able to parse. You now should end with something like this.
var culture = new CultureInfo("en-US");
var formats = new string[] {
#"s\.f",
#"ss\.f",
#"ss\.ff",
#"m\:ss\.f",
#"m\:ss\.ff",
#"mm\:ss\.ff"
};
foreach ( var str in new string[] { "27.0", "52.4", "1:24.4", "1:43.3" } ) {
var ts = TimeSpan.ParseExact(str, formats, culture.NumberFormat);
Console.WriteLine(ts.ToString());
}
Note that in this example I added a backslash to escape the dot and the colon. If you don't do this then the formatter itself treats this as a culture-sensitive separator. But what you want is exactly the colon or the dot.
The output of this code will be
00:00:27
00:00:52.4000000
00:01:24.4000000
00:01:43.3000000

try something like this:
var timeString = "1:24.4";
var timeComponents = timeString.Split(':', '.').Reverse().ToList();
var milliseconds = timeComponents.Any() ? int.Parse(timeComponents[0]) : 0;
var seconds = timeComponents.Count() > 1 ? int.Parse(timeComponents[1]) : 0;
var minutes = timeComponents.Count() > 2 ? int.Parse(timeComponents[2]) : 0;
var timeSpan = new TimeSpan(0, 0, minutes, seconds, milliseconds);
this will deal with the milliseconds literally. You may want to pad the string component of the milliseconds with '0's, as pointed out in the comments.

Related

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.

How to parse a string to DateTime with "yyyyMMdd Hmm" format?

I'm having huge problems with solving this problem. I'm trying to parse a string using Datetime.ParseExact().
I have the following code:
DateTime.ParseExact("20151210 832", "yyyyMMdd Hmm", CultureInfo.InvariantCulture);
I get following error:
An unhandled exception of type 'System.FormatException' occurred in
mscorlib.dll Additional information: String was not recognized as a
valid DateTime.
What am I doing wrong? How can I solve this problem?
UPDATE:
I can also get times like this:
00:01 => 1
01:00 => 1
01:10 => 10
Since H specifier can be 2 digit, this method try to parse your 83 with H specifier. Since there is no such an hour, you get FormatException.
For your case, one way to prevent this is putting a leading zero just before your 8.
var s = "20151210 832";
var result = s.Split(' ')[0] + " 0" + s.Split(' ')[1];
var dt = DateTime.ParseExact(result, "yyyyMMdd Hmm", CultureInfo.InvariantCulture);
Be aware, this will not work for all cases. For example, if your hour part already two digit, if your single minute does not have leading zero.. etc.
Or you can put delimiter for your all parts but in such a case, you need to manipulate both your string and format.
.NET Team suggest this way as well.
Just insert a separator before minutes (for example, a whitespace) and then you can parse it like this:
string example = "20151210 832";
example = example.Insert(example.Length - 2, " ");
var dateTime = DateTime.ParseExact(example, "yyyyMMdd H mm", CultureInfo.InvariantCulture);
I assume that the datetime string always contains two digits specifying minutes (check an article about Custom Date and Time Format Strings). If my assumption is wrong then this string cannot be parsed.

Extracting a complicated date / time format out of a string

I am trying to find the best possible way to extract a Date and Time string that is stored in a very very strange format out of a file name (string) that was retrieved from an FTP file listing.
The string is as follows:
-rwxr-xr-x 1 ftp ftp 267662 Jun 06 09:13 VendorInventory_20130606_021303.txt\r
The specific data I am trying to extract is 20130606_021303. 021303 is formatted as hours, seconds and milliseconds. DateTime.Parse and DateTime.ParseExact are not willing to cooperate. Any idea on how to get this up and running?
Looks like you've got the entire row of the file listing, including permissions, user, owner, file size, timestamp and filename.
The data you're asking for appears to be just part of the filename. Use some basic string manipulation (Split, Substring, etc...) first. Then when you have just the datetime portion, you can then call DateTime.ParseExact.
Give it a try yourself first. If you run into problems, update your question to show the code you are attempting, and someone will help you further.
...
Oh, fine. What the heck. I'm feeling generous. Here's a one-liner:
string s = // your string as in the question
DateTime dt = DateTime.ParseExact(string.Join(" ", s.Split('_', '.'), 1, 2),
"yyyyMMdd HHmmss", null);
But please, next time, try something on your own first.
UPDATE I assume there is a fixed structure to the file display of the FTP listing, so you could simply use String.Substring to extract the datetime string, and then parse with DateTime.ParseExact:
var s = "-rwxr-xr-x 1 ftp ftp 267662 Jun 06 09:13 VendorInventory_20130606_021303.txt\r";
var datetime = DateTime.ParseExact(s.Substring(72,15),"yyyyMMddHHmmss",null);
Original Answer
Use a regular expression. Try the following:
var s = "-rwxr-xr-x 1 ftp ftp 267662 Jun 06 09:13 VendorInventory_20130606_021303.txt\r";
/*
The following pattern means:
\d{8}) 8 digits (\d), captured in a group (the parentheses) for later reference
_ an underscore
(\d{6}) 6 digits in a group
\. a period. The backslash is needed because . has special meaning in regular expressions
.* any character (.), any number of times (*)
\r carriage return
$ the end of the string
*/
var pattern = #"(\d{8})_(\d{6})\..*\r$";
var match = Regex.Match(s, pattern);
string dateString = matches.Groups[1].Value;
string timeString = matches.Groups[2].Value;
and parse using ParseExact:
var datetime = DateTime.ParseExact(dateString + timeString,"yyyyMMddHHmmss",null);
This might work:
string s = "-rwxr-xr-x 1 ftp ftp 267662 Jun 06 09:13 VendorInventory_20130606_021303.txt\r";
// you might need to adjust the IndexOf method a bit - if the filename/string ever changes...
// or use a regex to check if there's a date in the given string
// however - the first thing to do is extract the dateTimeString:
string dateTimeString = s.Substring(s.IndexOf("_") + 1, 15);
// and now extract the DateTime (you could also use DateTime.TryParseExact)
// this should save you the trouble of substringing and parsing loads of ints manually :)
DateTime dt = DateTime.ParseExact(dateTimeString, "yyyyMMdd_hhmmss", null);

Convert TimeSpan from format "hh:mm:ss" to "hh:mm"

I want to show in a TextBox only hour and minutes
var test = dataRow.Field<TimeSpan>("fstart").ToString();
//test ="08:00:00"
var tb = (TextBox) gridViewRow.Cells[2].FindControl("fstart");
tb.Text = test;
how to show only hours and minutes "hh.mm"
You need to convert your data to TimeSpan and then use format:"hh\:mm"
string test ="08:00:00";
TimeSpan ts = TimeSpan.Parse(test);
Console.Write(ts.ToString(#"hh\:mm"));
In your case:
var test = dataRow.Field<TimeSpan>("fstart").ToString(#"hh\:mm"));
Remember to escape the colon :
You may see: Custom TimeSpan Format Strings
There is no need to convert from hh.mm.ss to hh.mm. TimeSpan is stored as a number of ticks (1 tick == 100 nanoseconds) and has no inherent format. What you have to do, is to convert the TimeSpan into a human readable string! This involves formatting. If you do not specify a format explicitly, a default format will be used. In this case hh.mm.ss.
string formatted = timespan.ToString(#"hh\.mm");
Note: This overload of ToString exists since .NET 4.0. It does not support date and time placeholder separator symbols! Therefore you must include them as (escaped) string literals.
The usual way of formatting strings seems not to work for some odd reason (tested with .NET 3.5). (It does not make any difference whether you escape the separator symbol or not):
var timespan = TimeSpan.FromSeconds(1234);
string formatted = String.Format(#"{0:hh\.mm}", timespan); // ==> 00:20:34
However, you can construct the string like this
string formatted =
String.Format("{0:00}.{1:00}", Math.Floor(timespan.TotalHours), timespan.Minutes);
or starting with VS2015 / C# 6.0, using string interpolation:
string formatted = $#"{timespan:hh\:mm}";
You can use TimeSpan methods:
ToString("hh':'mm")
// or
ToString(#"hh\:mm")
Also check all available formats here http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
var test = dataRow.Field<TimeSpan>("fstart").ToString("hh.mm");
//test ="08:00"
var tb = (TextBox) gridViewRow.Cells[2].FindControl("fstart");
tb.Text = test;
I know this is a very old question. If anyone wants to show single-digit hours when your hours are a single digit then you can use
var hoursWithMinutes = TimeSpan.FromHours(hours).ToString(#"h\:mm")
This way, when your hours are double-digit I mean greater than 9 then it will be showing 10:00 something like that.
The previous solutions don't run if hours>24, try this solution if you have time in minutes very big
int minutes = 159000;
TimeSpan t = new TimeSpan(0, minutes, 0);
String HOURS = Math.Round(t.TotalHours, 0).ToString();
if (HOURS.Length==1)
{
HOURS = "0"+HOURS;
}
String MINUTES = t.Minutes.ToString();
if (MINUTES.Length == 1)
{
MINUTES = "0" + MINUTES;
}
String RESULT = HOURS + ":" + MINUTES;
You can achieve this by:
var hhmm = TimeSpan.FromMinutes(minutes).ToString(#"hh\:mm")

How do I convert an integer into an ISO8601 TimeSpan?

This is my input:
55
This is my desired output:
PT55H
Is there a built in class in C# that converts a timespan as: TimeSpan.TryParse(55) or as a string "55" with hours into an ISO8601 formatted string?
You can convert a number to a TimeSpan with the static TimeSpan.FromHours method. For example var ts = TimeSpan.FromHours(55.0);.
If you always want the time represented with hours only, in the ISO system, maybe you can simply say var isostring = String.Format("PT{0}H", ts.TotalHours);.
Coworker just found this for me:
TimeSpan start = new TimeSpan(int.Parse(txtStartHours.Text), 0, 0);
durationNode.Element("StartTime").Value = XmlConvert.ToString(start);
It seems to convert it to PT2D7H, but since I'm using XMLConvert.ToTimeSpan().TotalHours elsewhere, it shouldn't cause any problems!

Categories

Resources