I have a timespan value which is difference of two Datetime values. It is like this :
myvalue = {41870.01:44:22.8365404}
I have also a string which represents another timespan value and it is like this :
ttime= "23:55" // which means 23 minutes and 55 seconds
I want to check if myvalue is smaller than ttime. Here is my attempt:
if(myvalue < Timespan.Parse(ttime))
//do this
else
//do that
Is my approach correct enough? Do I need to do something else? Thanks.
The only problem i can see is that TimeSpan.Parse is limited to 24 hours. So you would need this workaround:
string ttime = "48:23:55"; // 48 hours
TimeSpan ts = new TimeSpan(int.Parse(ttime.Split(':')[0]), // hours
int.Parse(ttime.Split(':')[1]), // minutes
int.Parse(ttime.Split(':')[2])); // seconds
Apart from that it's absolutely fine to compare two timespan in this way.
If it can contain two or three parts(with or without hours), this should be safer:
string[] tokens = ttime.Split(':');
// support only two or three tokens:
if (tokens.Length < 2 || tokens.Length > 3)
throw new NotSupportedException("Timespan could not be parsed successfully: " + ttime);
TimeSpan ts;
if(tokens.Length == 3)
ts = new TimeSpan(int.Parse(tokens[0]), int.Parse(tokens[1]),int.Parse(tokens[2]));
else
ts = new TimeSpan(0, int.Parse(tokens[0]), int.Parse(tokens[1]));
For what it's worth, here is a method which is written from scratch which parses a string to TimeSpan by allowing two or three tokens(hh,mm,ss or mm,ss) and also supports weird formats like 100:100:100 (100 hours + 100 minutes + 100 seconds):
public static TimeSpan SaferTimeSpanParse(string input, char delimiter = ':')
{
if (string.IsNullOrEmpty(input))
throw new ArgumentNullException("input must not be null or empty", "input");
string[] tokens = input.Split(delimiter);
if (tokens.Length < 2 || tokens.Length > 3)
throw new NotSupportedException("Timespan could not be parsed successfully: " + input);
int i;
if (!tokens.All(t => int.TryParse(t, out i) && i >= 0))
throw new ArgumentException("All token must contain a positive integer", "input");
int[] all = tokens.Select(t => int.Parse(t)).ToArray();
int hoursFinal = 0, minutesFinal = 0, secondsFinal = 0;
int seconds = all.Last();
secondsFinal = seconds % 60;
minutesFinal = seconds / 60;
int minutes = (all.Length == 3 ? all[1] : all[0]) + minutesFinal; // add current minutes which might already be increased through seconds
minutesFinal = minutes % 60;
hoursFinal = minutes / 60;
hoursFinal = all.Length == 3 ? all[0] + hoursFinal : hoursFinal; // add current hours which might already be increased through minutes
return new TimeSpan(hoursFinal, minutesFinal, secondsFinal);
}
tested with your string, my string and a weird one:
Console.WriteLine(SaferTimeSpanParse("23:55"));
Console.WriteLine(SaferTimeSpanParse("48:23:55"));
Console.WriteLine(SaferTimeSpanParse("100:100:100"));
Output:
00:23:55
2.00:23:55
4.05:41:40
Related
This question already has answers here:
Convert TimeSpan from format "hh:mm:ss" to "hh:mm"
(7 answers)
Closed 4 years ago.
Beginner in xamarin. Im tring to display the time as HH:mm without the seconds being added in. It appears on my form as example 12:30:00, i want just as 12:30. Do i need to change Date time function maybe, the code is currently working but displaying the time as hour minute seconds still.
The code also should allow the soonest time to appear at the top but it doesnt seem to be doing that either.
void FindNextDue(ObservableCollection<UserMedDosagePayLoad> medtimes)
{
UserMedTimesFilteredList.Clear();
int nowHour = DateTime.Now.Hour;
int nowMinutes = DateTime.Now.Minute;
TimeSpan now = new TimeSpan(nowHour, nowMinutes, 0);
foreach (UserMedDosagePayLoad item in medtimes)
{
item.Nextduemessage = item.Dosage + " " + item.Dosageunit +
"due at " + item.Time;
string[] DT = item.Time.Split(':');
if (DT[0] != null)
{
int hr = Convert.ToInt32(DT[0]);
int minutes = Convert.ToInt32(DT[1]);
TimeSpan medTime = new TimeSpan(hr, minutes, 0);
TimeSpan comparison = now.Subtract(medTime).Negate();
TimeSpan TwentyFourHour = new TimeSpan(24, 0, 0);
if (comparison.TotalMilliseconds <0)
{
comparison = TwentyFourHour.Add(comparison);
}
TimeComparison.Add(comparison);
}
}
//Order the collection of times so the next due is always first
TimeComparison = new List<TimeSpan>(TimeComparison.OrderBy(h => h.Hours)
.ThenBy(m => m.Minutes));
List<string> UserMedIDs = new List<string>();
for (int i = 0; i < TimeComparison.Count(); i++)
{
DateTime NextDue = DateTime.Now.Add(TimeComparison[i]);
DateTime NextDueToCompare = new DateTime(NextDue.Year, NextDue.Month,
NextDue.Day, NextDue.Hour, NextDue.Minute, 0);
string NextDueComparisonString = NextDueToCompare.ToString("HH:mm:ss");
foreach (UserMedDosagePayLoad item in UserMedTimes)
{
if (item.Time == NextDueComparisonString &&
!UserMedIDs.Contains(item.Usermedid))
{
UserMedTimesFilteredList.Add(item);
UserMedIDs.Add(item.Usermedid);
}
}
UserMedTimes = medtimes;
MedicationList.ItemsSource = UserMedTimesFilteredList;
BusyIndicator.IsRunning = false;
}
}
If you only want hours and minutes to display, then remove "ss" from your format string
string NextDueComparisonString = NextDueToCompare.ToString("HH:mm:ss");
here, you are not specifying any format so it is using the default
item.Nextduemessage = item.Dosage + " " + item.Dosageunit +
"due at " + item.Time;
specify a format like this
item.Nextduemessage = item.Dosage + " " + item.Dosageunit +
"due at " + item.Time.ToString("HH:mm");
Use formatting if you don't want to see the seconds at all (12:48 for example).
The method gets a TimeSpan obj, and returns the time as a string without the seconds.
Read here to explore more about formatting.
The custom function
public string GetTimeSpanWithoutSeconds(TimeSpan input)
{
return input.ToString(#"hh\:mm");
}
The "hh" custom format specifier
Represents the hour as a number from 01 through 12; that is, the hour is represented by a 12-hour clock that counts the whole hours since midnight or noon. A particular hour after midnight is indistinguishable from the same hour after noon. The hour is not rounded, and a single-digit hour is formatted with a leading zero. For example, given a time of 5:43 in the morning or afternoon, this format specifier displays "05".
The "mm" custom format specifier
Represents the minute as a number from 00 through 59. The minute represents whole minutes that have passed since the last hour. A single-digit minute is formatted with a leading zero.
I am trying to make a digital clock in C#. I have 3 counter objects for hours, minutes and seconds. It has to be in format hh:mm:ss.
What I managed to do
String hours = _hours.Value.ToString();
String minutes = _minutes.Value.ToString();
String seconds = _seconds.Value.ToString();
if (hours.Length == 1)
{
hours = "0" + hours;
}
if (minutes.Length == 1)
{
minutes = "0" + minutes;
}
if (seconds.Length == 1)
{
seconds = "0" + seconds;
}
return hours + ":" + minutes + ":" + seconds;
It works but I am trying for a more efficient way of doing it using String.format. I have tried few different regular expressions but have been unsuccessful.
string b = string.Format("{0:D2}:{1:00}:{2:d2}", hours, minutes, seconds);
Cheers
Have you tried converting the string into int, before trying your string.Format? Something like below
string.Format("{0:00}:{1:00}:{2:00}",
int.Parse(hours), int.Parse(minutes), int.Parse(seconds));
If _hours.Value, _minutes.Value and _seconds.Value are numeric types, then you can use the below code which is more efficient
string.Format("{0:00}:{1:00}:{2:00}",
_hours.Value, _minutes.Value, _seconds.Value);
You can always try something a bit different:
DateTime dt = new DateTime(2000, 1, 1, hours, minutes, seconds); // just ignore year, month and day
var x = dt.ToString("HH:mm:ss");
IMO if you already have a string type it's useless to cast it to int or DateTime just to stringify it again after that.
I would use String.PadLeft method :
string h = hours.PadLeft(2, '0');
string m = minutes.PadLeft(2, '0');
string s = seconds.PadLeft(2, '0');
string result = h + ":" + m + ":" + s;
PadLeft will make your string to always have length at least of the value passed as a first parameter ( 2 in this case ) and fill "empty" places with the value passed in second parameter ( 0 in this case ).
Check this online
You can use the formatting options available on the ToString() method of DateTime like below:
(new DateTime(1900, 1, 1, _hours.Value, _minutes.Value, _seconds.Value)).ToString("HH:mm:ss");
You can try using:
string b = DateTime.Now.ToString("HH:mm:ss");
If you have some date variable, you can do so:
string b = dateVar.ToString("HH:mm:ss");
If you want solution exactly for your example, then:
return string.Format("{0:00}:{1:00}:{2:00}",
int.Parse(hours),
int.Parse(minutes),
int.Parse(seconds)
);
I have a code in c# and I need to accumulate all the hours in a DateTime format.
I have a foreach statement where I calculate pending hours but that pending hours need to be accumulated so at the end I have a total of hours and minutes and based on a day limit hours for example my day could be a 8 hours day, then I can format it as string like the following example:
If my total hours is: 24 hours 31 minutes then based on a 8 hour day I should format as follows:
3 days, 31 minutes.
I need to know the best way to accumulate the hours, here is the code that is inside my foreach:
// here I create a Timespan in order to get hours and minutes from a DB.
var timeSpan = TimeSpan.FromHours(double.Parse(drItem["PayableHours"].ToString()));
int hh = timeSpan.Hours;
int mm = timeSpan.Minutes;
int ss = timeSpan.Seconds;
// pending hours
// here i create a tempHours variable for a 8 hour
DateTime tempHours = new DateTime(1900, 1, 1, 8, 0, 0);
// here I substract from my 8 hour datetime the hours and the minutes of my timespan
DateTime pendingHours = dayHours.Add(new TimeSpan(-hh,-mm,0));
// here i should accumulate the pendingHours so when the foreach statement finish I can format the total hours and minutes to string.
Any clue?
From what I understand, it would look something like this:
private static string PrettyPrint(TimeSpan timeSpan)
{
var parts = new List<string>();
int totalHours = (int)timeSpan.TotalHours;
int workDays = totalHours / 8;
int remainingHours = (int)timeSpan.TotalHours - 8 * workDays;
if (workDays == 1) parts.Add("1 day");
if (workDays > 1) parts.Add(workDays + " days");
if (remainingHours == 1) parts.Add("1 hour");
if (remainingHours > 1) parts.Add(timeSpan.Hours + " hours");
if (timeSpan.Minutes == 1) parts.Add("1 minute");
if (timeSpan.Minutes > 1) parts.Add(timeSpan.Minutes + " minutes");
return string.Join(", ", parts);
}
You might want to also add some code to check for TimeSpan.Zero.
If I understand your question correctly, then:
int numberDays = hh / 8;
will give you the number of days. From there, the rest should be easy.
I am to fill a ddl at run time.
What I actually need to do is pick up the current time from the system (in 24-hour format).
Then I need to round it up to a 15 min slot, so if the time is 13:23 it will become 13:30; if it is 13:12 then it should become 13:15.
Then I want to add 45 minutes to it, and 13:15 becomes 14:00.
I am trying to achieve it like this
DateTime d = DateTime.Now;
string hr = d.ToString("HH:mm");
string mi = d.ToString("mm");
Could somebody tell, either I have to write all logic or DateTime can provide some feature
to format it like this?
I think this should do the trick for you:
var d = DateTime.Now;
d = d.AddSeconds(-d.Seconds).AddMilliseconds(-d.Milliseconds)
if (d.Minute < 15) { d.AddMinutes(15 - d.Minute); }
else if (d.Minute < 30) { d = d.AddMinutes(30 - d.Minute); }
else if (d.Minute < 45) { d = d.AddMinutes(45 - d.Minute); }
else if (d.Minute < 60) { d = d.AddMinutes(60 - d.Minute); }
d = d.AddMinutes(45);
DateTime d = DateTime.Now;
//Add your 45 minutes
d = d.AddMinutes(45);
//Add minutes to the next quarter of an hour
d = d.AddMinutes((15 - d.TimeOfDay.Minutes % 15) % 15);
//Show your result
string hr = d.ToString("HH:mm");
string mi = d.ToString("mm");
DateTime in C# has a function for adding any increment to the current DateTime object. Here is a reference to the specific function for minutes.
DateTime d = DateTime.Now;
DateTime rounded;
if(d.Minute % 15 ==0)rounded = d;
else DateTime rounded = d.AddMinutes(15 - d.Minute % 15);
Console.WriteLine("{0:HH:mm}",rounded);
Hello i got array of string, and they are durations made by myself in format H:M:S:MS
Example strings:
0:0:4:410
0:0:1:425
0:0:1:802
0:0:1:509
0:0:1:674
0:0:1:628
0:0:2:76
How can i sum/avg/min/max values of these items in arraylist?
Arraylist name is arrayLL.
I'm new in c# so hope someone will show me how to work with strings.
The function that adds to array is:
if (Session["DT"].ToString() != "")
{
TimeSpan ts = ((DateTime)Session["DT2"]).Subtract((DateTime)Session["DT"]);
Session["TimeL"] = ts.Hours.ToString() + ":"
+ ts.Minutes.ToString() + ":"
+ ts.Seconds.ToString() + ":"
+ ts.Milliseconds.ToString();
}
Assuming the numbers represent hours, minutes, seconds, and milliseconds you can try the following:
// Empty list you will populate:
List<int> durationsInMilliseconds = new List<int>();
// Loop through your existing data, and calculate all
// durations into milliseconds:
foreach (string word in yourDurationArray)
{
string[] values = s.Split(':');
int hoursAsMilliseconds = Integer.parse(values[0]) * 60 * 60 * 1000;
int minutesAsMilliseconds = Integer.parse(values[1]) * 60 * 1000;
int secondsAsMilliseconds = Integer.parse(values[2]) * 1000;
int sumDurationAsMilliseconds = hoursAsMilliseconds +
minutesAsMilliseconds +
secondsAsMilliseconds +
Integer.parse(values[3]);
durationsInMilliseconds.add(sumDurationAsMilliseconds);
}
Now you should have a list of type Integer (durationsInMilliseconds) which contains the numbers in a single comparable format. With this, you should be able to do whichever calculations you need.
(PS: If you need the result in the same format as the original input-data, you will have to add an operation for calculating back from MS into hours, minutes and seconds..)
Since i guess they are Durations so i you should do this
var enu_ts = yourvariable.OfType<string>().Select(x =>
TimeSpan.Parse(x, #"h\:m\:s\:fff", CultureInfo.InvariantCulture));
Max
var max = enu_ts.Max().ToString();
Min
var max = enu_ts.Min().ToString();
foreach(string s in dateString)
{
spanList[i] = TimeSpan.Parse(s);
total=total.Add(spanList[i++]);
}
Response.Write("Max TimeSpan:"+spanList.Max<TimeSpan>());
Response.Write("Min TimeSpan:" + spanList.Min<TimeSpan>());
Response.Write("Total Sum of TimeSpan:"+total);