Rounding up a time to the nearest hour - c#

ok basically I have a program that is re-writing text files and formatting them through various conditions, one of the conditions is that the date and time values in my original text file needs to be removed from its current location and moved into a new column I have created, this is done with the code below. I used a regex to find the date and time format and then remove it from its current location and store the value in a variable that I can use later...
if (line.Contains(date))
{
string pattern = #"(\d{2}:\d{2}:\d{2}\s?\d{2}/\d{2}/\d{4})";
string input = line;
string replacement = "";
Regex rgx = new Regex(pattern);
date1 = rgx.Match(input).ToString();
string result = rgx.Replace(input, replacement);
line = result;
}
This new value that is returned gets both the time and date values but only as one string, so I then used a split (shown below) to get the two values separate, now split[0] is my time variable (00/00/00 format) - which I now need to round up to the nearest hour. I am really not sure how to go about this, any ideas ?
string[] split = date1.Split(' ');
writer.WriteLine(split[0] + "\t" + split[1] + "\t" + line);

Get that date from the string into a DateTime struct. See for example the TryParseExact method
Then you can create a new DateTime value, based on year/month/day/hour of the value from the previous step, setting the minute and second parts to zero (see here )
Add one hour if the minutes or seconds part (of your first value) is not zero, using .AddHours(1), which returns a new DateTime value.
EDIT
Some sample code:
string inputdate = "2:56:30 8/7/2014";
DateTime dt;
System.Globalization.CultureInfo enUS = new System.Globalization.CultureInfo("en-US");
if (DateTime.TryParseExact(inputdate, "H:m:s d/M/yyyy", // hours:minutes:seconds day/month/year
enUS, System.Globalization.DateTimeStyles.None, out dt))
{
// 'dt' contains the parsed date: "8-7-2014 02:56:30"
DateTime rounded = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0);
if (dt.Minute > 0 || dt.Second > 0) // or just check dt.Minute >= 30 for regular rounding
rounded = rounded.AddHours(1);
// 'rounded' now contains the date rounded up: "8-7-2014 03:00:00"
}
else
{
// not a correct date
}

In my case, I need to round it to lower hour, and I used this logic:
DateTime x = new DateTime();
x = x.Date.AddHours(x.Hour);

You can try one liner solution to convert your DateTime to nearest hour,
//Input DateTime
DateTime input = DateTime.ParseExact("28/05/2021 2:16 PM", "dd/MM/yyyy h:mm tt", CultureInfo.InvariantCulture);
//Ternary Operation
var output = input.Minute > 30 //Check if mins are greater than 30
? input.AddHours(1).AddMinutes(-input.Minute) //if yes, then add one hour and set mins to zero
: input.AddMinutes(-input.Minute); //otherwise set mins to zero
Console.WriteLine(result.ToString());
Try Online: .NET Fiddle

Can you convert the string to a datetime?
Something like:
dateVariable = Convert.ToDateTime(dateString);
int hour = dateVariable.Hour;
int minute = dateVariable.Minute;
And then do the rounding.

Now as you have
string[] str = split[1].Split('/');
// create a new DateTime
int minutes = int.Parse(str[1]);
if(minutes >= 30)
hour = int.Parse(str[0]) + 1 // make sure if it 13 or 25 make it 1
minutes = 0 ;
sec = 0;
else {
hour = int.Parse(str[0]);
minutes = 0 ;
sec = 0 ;
}
var myDate = new Date(Year, month , day , hour , minutes , sec);

In C#
var Now = DateTime.Now;
var Nearest = Now.Date;
Nearest = Nearest.AddHours(Now.Hour + (Now.Minute >= 30 ? 1 : 0));
Now = Current time
Nearest = Rounded to the nearest hour

Related

Check if less than 7 days before ending [duplicate]

I see that this question has been answered for Java, JavaScript, and PHP, but not C#. So, how might one calculate the number of days between two dates in C#?
Assuming StartDate and EndDate are of type DateTime:
(EndDate - StartDate).TotalDays
The top answer is correct, however if you would like only WHOLE days as an int and are happy to forgo the time component of the date then consider:
(EndDate.Date - StartDate.Date).Days
Again assuming StartDate and EndDate are of type DateTime.
Use TimeSpan object which is the result of date substraction:
DateTime d1;
DateTime d2;
return (d1 - d2).TotalDays;
I think this will do what you want:
DateTime d1 = DateTime.Now;
DateTime d2 = DateTime.Now.AddDays(-1);
TimeSpan t = d1 - d2;
double NrOfDays = t.TotalDays;
DateTime xmas = new DateTime(2009, 12, 25);
double daysUntilChristmas = xmas.Subtract(DateTime.Today).TotalDays;
// Difference in days, hours, and minutes.
TimeSpan ts = EndDate - StartDate;
// Difference in days.
int differenceInDays = ts.Days; // This is in int
double differenceInDays= ts.TotalDays; // This is in double
// Difference in Hours.
int differenceInHours = ts.Hours; // This is in int
double differenceInHours= ts.TotalHours; // This is in double
// Difference in Minutes.
int differenceInMinutes = ts.Minutes; // This is in int
double differenceInMinutes= ts.TotalMinutes; // This is in double
You can also get the difference in seconds, milliseconds and ticks.
In case someone wants numer of whole days as a double (a, b of type DateTime):
(a.Date - b.Date).TotalDays
There often is a debate on time (hours) when it comes to counting days between two dates. The responses to the question and their comments show no exception.
Considering StartDate and EndDate are of type DateTime: if performance is not a concern, I would strongly recommend documenting your calculation through intermediate conversions. For example, (EndDate - StartDate).Days is unintuitive because rounding will depend on the hour component of StartDate and EndDate.
If you want the duration in days to include fractions of days, then as already suggested
use (EndDate - StartDate).TotalDays.
If you want the duration to reflect
the distance between two days, then use (EndDate.Date - StartDate.Date).Days
If you want the duration to reflect the
duration between the morning of the start date, and the evening of
the end date (what you typically see in project management software), then use
(EndDate.Date - StartDate.Date).Days + 1
You can try this
EndDate.Date.Subtract(DateTime.Now.Date).Days
Using a timespan would solve the problems as it has many attributes:
DateTime strt_date = DateTime.Now;
DateTime end_date = Convert.ToDateTime("10/1/2017 23:59:59");
//DateTime add_days = end_date.AddDays(1);
TimeSpan nod = (end_date - strt_date);
Console.WriteLine(strt_date + "" + end_date + "" + "" + nod.TotalHours + "");
Console.ReadKey();
For a and b as two DateTime types:
DateTime d = DateTime.Now;
DateTime c = DateTime.Now;
c = d.AddDays(145);
string cc;
Console.WriteLine(d);
Console.WriteLine(c);
var t = (c - d).Days;
Console.WriteLine(t);
cc = Console.ReadLine();
For beginners like me that will stumble upon this tiny problem, in a simple line, with sample conversion to int:
int totalDays = Convert.ToInt32((DateTime.UtcNow.Date - myDateTime.Date).TotalDays);
This calculates the total days from today (DateTime.UtcNow.Date) to a desired date (myDateTime.Date).
If myDateTime is yesterday, or older date than today, this will give a positive (+) integer result.
On the other side, if the myDateTime is tomorrow or on the future date, this will give a negative (-) integer result due to rules of addition.
Happy coding! ^_^
First declare a class that will return later:
public void date()
{
Datetime startdate;
Datetime enddate;
Timespan remaindate;
startdate = DateTime.Parse(txtstartdate.Text).Date;
enddate = DateTime.Parse(txtenddate.Text).Date;
remaindate = enddate - startdate;
if (remaindate != null)
{
lblmsg.Text = "you have left with " + remaindate.TotalDays + "days.";
}
else
{
lblmsg.Text = "correct your code again.";
}
}
protected void btncal_Click(object sender, EventArgs e)
{
date();
}
Use a button control to call the above class. Here is an example:
You can use the code below:
int DateDifInSecond = EndDate.Subtract(StartDate).TotalSeconds
Get the difference between the two dates and then get the days from:
int total_days = (EndDate - StartDate).TotalDays
try this truly worked Get actual days diff. date format is "dd/MM/yyyy"
string[] d1 = txtFromDate.Values.Split('/');
string[] d2 = txtToDate.Values.Split('/');
DateTime FrmDt = new DateTime(Convert.ToInt32(d1[2]), Convert.ToInt32(d1[1]), Convert.ToInt32(d1[0]));
DateTime ToDt = new DateTime(Convert.ToInt32(d2[2]), Convert.ToInt32(d2[1]), Convert.ToInt32(d2[0]));
TimeSpan TDiff = ToDt.Subtract(FrmDt);
String DaysDiff = TDiff.TotalDays.ToString();
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
DateTime d = Calendar1.SelectedDate;
// int a;
TextBox2.Text = d.ToShortDateString();
string s = Convert.ToDateTime(TextBox2.Text).ToShortDateString();
string s1 = Convert.ToDateTime(Label7.Text).ToShortDateString();
DateTime dt = Convert.ToDateTime(s).Date;
DateTime dt1 = Convert.ToDateTime(s1).Date;
if (dt <= dt1)
{
Response.Write("<script>alert(' Not a valid Date to extend warranty')</script>");
}
else
{
string diff = dt.Subtract(dt1).ToString();
Response.Write(diff);
Label18.Text = diff;
Session["diff"] = Label18.Text;
}
}

How to remove seconds from TimeSpan? [duplicate]

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.

Compare 2 strings of time in C#

So I've got a string 00:00:15:185 which I need to tell is greater than 15 seconds.
Time format is HH:m:ss:FFF
This is clearly longer than 15 seconds but I can't compare it properly.
Current code is this:
value = "00:00:15:185";
if (DateTime.Parse(value) > DateTime.Parse("00:00:15:000"){
//do stuff
}
It's giving exceptions when I run it all the time and the program doesn't work when it should
Your string doesn't represent a time, but an amount of time. We have TimeSpan for that.
var value = "00:00:15:185";
if (TimeSpan.ParseExact(value, #"hh\:mm\:ss\:FFF", CultureInfo.InvariantCulture)
> TimeSpan.FromSeconds(15))
{
//do stuff
}
Another option(apart from #rob 's answer), use DateTime.ParseExact
var value = "00:00:15:185";
if (DateTime.ParseExact(value, "HH:mm:ss:fff", CultureInfo.InvariantCulture) >
DateTime.ParseExact("00:00:15:000", "HH:mm:ss:fff", CultureInfo.InvariantCulture))
{
// logic here.
}
DateTime time = DateTime.Now;
String result = time.ToString("HH:mm ");
DateTime firstTimr = DateTime.ParseExact(reader["shift_start_time"].ToString(), "HH:mm:tt", null);
String firstTimr1 = firstTimr.ToString("HH:mm ");
DateTime lastTime = DateTime.ParseExact(reader["Shift_last_time"].ToString(), "HH:mm:tt", null);
String lastTime1 = lastTime.ToString("HH:mm ");
if (DateTime.Parse(result) >= DateTime.Parse(firstTimr1) && (DateTime.Parse(result) <= DateTime.Parse(lastTime1)))
{
`enter code here` MessageBox.Show("First Shit");
}

How To Display Date In Locale For 0 Values?

Ok, so I have a date stored in UK format (dd/mm/yy) which I need to display in the locale of wherever the user might be.
The issue is that this date can be 000000 (00/00/2000); so I can't convert it to DateTime directly, as DateTime doesn't support 0 values for day or month.
I have this so far:
int dateInt = ddmmyy;
var year = (dateInt % 100) + 2000;
var month = (dateInt / 100) % 100;
var day = (dateInt / 100000);
var result = new DateTime(year, month, day); //2014/00/00 at this point, so breaks.
var resultStr = result.ToString(CultureInfo.InvariantCulture);
return resultStr;
What's the correct way to add support for 0 values initially? I've tried changing the 0 to 1 before converting to DateTime, running the conversion and then replacing with a 0 again; but due to culture variants I see no way that this method can support other cultures, which is the purpose of this conversion to begin with.
Any ideas? I'm guessing this is a common issue.
Is this what you need ?
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
int[] savedDates = new int[] { 000000, 010000, 000013 };
foreach (var item in savedDates)
{
DateTime date = ConvertToDate(item);
Console.WriteLine(item.ToString("D6") + " => " + date.ToShortDateString());
}
Console.ReadLine();
}
private static DateTime ConvertToDate(int item)
{
string temp = item.ToString("D6");
int day = int.Parse(temp.Substring(0, 2));
int month = int.Parse(temp.Substring(2, 2));
int year = int.Parse(temp.Substring(4, 2));
if (day == 0)
day = 1;
if (month == 0)
month = 1;
year += 2000;
return new DateTime(year, month, day);
}
}
}
I would not store dates like this as the methodology for doing so is already provided by the .NET framework.
The best way to store dates would be to use Culture.InvariantCulture for string conversion cases and then convert to local culture for display purposes as necessary. DateTime itself is culture-independent so converting between cultures is very easy.

how can i get the interval in hrs AM to PM and PM to AM

i need help guys im creating an Overtime computation and when im trying to get the value of the value hrs it became negative when i subtract the PM to AM and PM to PM coz i need to count the hrs when it reach at 10:00 PM heres my code
string value = comboBox91.Text;
string value2 = comboBox92.Text;
string awtsu = value;
DateTime dt;
DateTime dt2;
dt = DateTime.Parse(value);
string mystring;
mystring = dt.ToString("hh:mm tt");
dt2 = DateTime.Parse(value2);
string mystring2;
mystring2 = dt2.ToString("hh:mm tt");
double diff2 = (dt2 - dt).TotalHours;
textBox8.Text = Convert.ToString(diff2) + "Hrs";
string pmm = "10:00 PM";
DateTime pm = DateTime.Parse(pmm);
string mystring3;
mystring3 = pm.ToString("hh:mm tt");
if (dt2 > pm)
{
double diff = (dt - dt2).TotalHours;
textBox9.Text = Convert.ToString(diff) + "Hrs";
}
else
{
textBox9.Text = ("0");
}
$
Let me see if I understand your requirements:
A worker starts at a standard time (8:30 AM) and usually finish at a standard time (6:30 PM), but may work later. In theory that person might work past midnight into the next day.
If they work past 7 PM up to 10 PM they get paid one overtime rate.
If they work past 10 those hours are paid a second rate.
So, the first thing you would declare in your code is a list of these overtime boundaries:
public static readonly TimeSpan[] OvertimeBoundaries =
{
TimeSpan.FromHours(19), // 7 PM
TimeSpan.FromHours(22) // 10 PM.
};
TimeSpan is a structure that represents an interval of time and is appropriate to represent a daily event.
Next, given a workers start and end times, you want to measure the total number of hours for each of these intervals:
public static TimeSpan[] GetOvertimeWorked(DateTime startDateTime, DateTime endDateTime, IList<TimeSpan> overtimeBoundaries)
{
var overtimeWorked = new TimeSpan[overtimeBoundaries.Count];
for (int i = 0; i < overtimeBoundaries.Count - 1; i++)
{
var time1 = startDateTime.Date + overtimeBoundaries[i];
var time2 = startDateTime.Date + overtimeBoundaries[i + 1];
if (time1 > time2)
throw new ArgumentException("overtimeBoundaries are not in order");
if (endDateTime > time2)
overtimeWorked[i] = time2 - time1;
else if (endDateTime > time1)
overtimeWorked[i] = endDateTime - time1;
else
overtimeWorked[i] = TimeSpan.Zero;
}
if (overtimeWorked.Length > 0)
{
var timeLast = startDateTime.Date + overtimeBoundaries[overtimeBoundaries.Count - 1];
if (endDateTime > timeLast)
overtimeWorked[overtimeBoundaries.Count - 1] = endDateTime - timeLast;
else
overtimeWorked[overtimeBoundaries.Count - 1] = TimeSpan.Zero;
}
return overtimeWorked;
}
Finally you need to extract the appropriate date & time information from your user interface, call the above utility to get overtime hours worked, and display it.
Your code would be much more comprehensible if you named your variables meaningfully rather than with names like "dt2" and "awtsu". You should also, at the minimum, separate your business logic from the code that loads and unloads data from the user interface.
Finally, I will note that the following is dangerous:
string pmm = "10:00 PM";
DateTime pm = DateTime.Parse(pmm);
The problem here is that, if you pass "DateTime.Parse" a string with only a "time of day" component, it will fill in the date information with the current clock setting on your computer. This would likely produce random, hard to reproduce bugs if you put your application into production, because the app might or might not be run on a different day than the workers worked!

Categories

Resources