This question already has answers here:
Determine the difference between two DateTimes, only counting opening hours
(6 answers)
Closed 6 years ago.
I have a C# method like this:
public int GetWorkLogHours(DateTime? startDate, DateTime? endDate, string startTime, string endTime)
{
}
I have a table of Holiday in which all the holidays are saved. What this method supposed to do is to calculate the number of hours between the startDate and startTime to endDate and endTime.It needs to exclude weekends and also skip the holiday between the two dates.
For Example :
We work monday to friday 9:00 AM to 17:00 PM (8 hours). If the
startDate(1-3-2016) and startTime(9:00) and endDate(10-3-2016) and
endTime(13:00). In my Holiday table (8-3-2016) is holiday then it
should return 52 hours
I hope this will solve your problem.
string start = "2016-01-07 09:00:00.000";
string end = "2016-01-07 17:00:00.000";
DateTime firstDay = Convert.ToDateTime(start);
DateTime lastDay = Convert.ToDateTime(end);
if (firstDay > lastDay)
{
}
else
{
TimeSpan span = lastDay - firstDay;
int businessDays = span.Days + 1;
int fullWeekCount = businessDays / 7;
if (businessDays > fullWeekCount * 7)
{
int firstDayOfWeek = (int)firstDay.DayOfWeek;
int lastDayOfWeek = (int)lastDay.DayOfWeek;
if (lastDayOfWeek < firstDayOfWeek)
lastDayOfWeek += 7;
if (firstDayOfWeek <= 6)
{
if (lastDayOfWeek >= 7)
businessDays -= 2;
else if (lastDayOfWeek >= 6)
businessDays -= 1;
}
else if (firstDayOfWeek <= 7 && lastDayOfWeek >= 7)
businessDays -= 1;
}
businessDays -= fullWeekCount + fullWeekCount;
}
double hours = 8 * businessDays;
also if you have an array of holidays like, DateTime[] bankHolidays then you can exclude the holidays also.
// subtract the number of bank holidays during the time interval
foreach (DateTime bankHoliday in bankHolidays)
{
DateTime bh = bankHoliday.Date;
if (firstDay <= bh && bh <= lastDay)
--businessDays;
}
Related
I have user age, month and day something like 18 year 2 month and 5 days. I need to return user DateOfBirth using these params. How can I find user DateOfBirth from year, month and day?
I've found a solution and it's works for me.
public static DateTime GetDateOfBirth(int year, int month, int day)
{
var today = DateTime.Today;
int currentYear = today.Year;
int currentDay = today.Day;
int currentMonth = today.Month;
if (day >= currentDay)
{
currentMonth--;
currentDay += DateTime.DaysInMonth(currentYear, currentMonth);
}
if (month >= currentMonth)
{
currentMonth += 12;
currentYear--;
}
return new DateTime(currentYear - year, currentMonth - month, currentDay - day);
}
you can always use AddDays/Months/Years with negative number to actually subtract Days/Months/Years from date.
DateTime now = DateTime.Now;
Console.WriteLine("Today's Date:" + now.ToString());
int years = 18;
int months = 2;
int days = 5;
now = now.AddYears((-1) * years);
now = now.AddMonths((-1) * months);
now = now.AddDays((-1) * days);
Console.WriteLine("Date Of Birth:" + now.ToString());
return now;
How can I get the date of next coming Monday or next coming Friday in C#.
lets say today is Wednesday and I want to get date of coming Friday.
This is what I've done
DateTime time = DateTime.Now.Date;
DateTime NextFriday;
if (time.DayOfWeek == DayOfWeek.Wednesday)
{
NextFriday = DateTime.Now.AddDays(2);
}
with this approach I've to initiate 7 variables for each day and 7 conditions for ever day to find the next specific day.
Is there any better and clean code by which I can get the date of any of the next coming day.
Using the following
public int CalculateOffset(DayOfWeek current, DayOfWeek desired) {
// f( c, d ) = [7 - (c - d)] mod 7
// f( c, d ) = [7 - c + d] mod 7
// c is current day of week and 0 <= c < 7
// d is desired day of the week and 0 <= d < 7
int c = (int)current;
int d = (int)desired;
int offset = (7 - c + d) % 7;
return offset == 0 ? 7 : offset;
}
You can calculate how far you are from the desired day and then add that to the current date
DateTime now = DateTime.Now.Date;
int offset = CalculateOffset(now.DayOfWeek, DayOfWeek.Friday);
DateTime nextFriday = now.AddDays(offset);
DateTime today = DateTime.Today;
DateTime nextFriday = System.Linq.Enumerable.Range(0, 6)
.Select(i => today.AddDays(i))
.Single(day => day.DayOfWeek == DayOfWeek.Friday);
You should probably use a time library that supports this, such as NodaTime.
See date.Next(IsoDayOfWeek.Sunday) on https://nodatime.org/1.3.x/userguide/arithmetic
Here's an alternative solution (please don't use this):
DateTime F(DateTime t, DayOfWeek dayOfWeek) => t.AddDays((7 + (int)dayOfWeek - (int)t.DayOfWeek) % 7);
for (int i = 0; i < 7; i++)
Console.WriteLine((DayOfWeek)i + " " + F(DateTime.Now, (DayOfWeek)i));
Outputs (on Wednesday 4/25/2018):
Sunday 4/29/2018 12:00:00 AM
Monday 4/30/2018 12:00:00 AM
Tuesday 5/1/2018 12:00:00 AM
Wednesday 4/25/2018 12:00:00 AM
Thursday 4/26/2018 12:00:00 AM
Friday 4/27/2018 12:00:00 AM
Saturday 4/28/2018 12:00:00 AM
DayOfWeek is just an enum between 0 and 6, so with modular arithmetic you can use the difference between your date of interest and target day of week to compute the number of days you must add.
A quick warning, you need to take into account timezone of interest when you ask what is meant by "today". It means a different thing depending on which side of the date line you live.
using System;
public class Program
{
public static DateTime NextDayForDay(DayOfWeek dayOfWeek, DateTime occurringAfter)
{
return occurringAfter.AddDays(((dayOfWeek - occurringAfter.DayOfWeek + 6) % 7)+1);
}
public static void Main()
{
for (int i=0; i < 7; i++)
{
for (int j=0; j < 7; j++)
{
DayOfWeek dayOfWeek = (DayOfWeek)(((int)DayOfWeek.Sunday + j) % 7);
DateTime test = DateTime.Today.AddDays(i);
Console.WriteLine($"{test}=>Next {dayOfWeek} is {NextDayForDay(dayOfWeek, test)}");
}
}
}
}
I have a start date like "2015-03-10". I want to add 1.25 days per month for the current year from this start date. For example, I have start date "2015-03-10" then for this year the number of days will be 12.50. (1.25 days for each month from March month).
Given date : 2015-11-10 need to add days up to March 31st,2016 : 1.25 * 5 (as from November month, here 5 )(For every month add 1.25 days) Number of days for this year : 6.25
(year start calculated from April and year end considered as March.)
How can i do this in c# can any one help me to do this
Thanks in advance
This example ignores the days of the months, as per your post:
DateTime start;
DateTime end;
// assuming end > start
double value = 1.25 * (end.Month - start.Month + 12 * (end.Year - start.Year) + 1);
EDIT: I can help you to understand this line of code splitting in some steps:
DateTime start = DateTime.Now;
DateTime end = new DateTime(start.Year, 3, 31);
if (start.Month > 3)
end = end.AddYear(1);
double years = end.Year - start.Year;
double months = end.Month - start.Month + 1;
months += (years * 12);
double value = 1.25 * months;
I got it by following :
DateTime endDate = new DateTime(DateTime.Today.Year + 1, 4, 1).AddDays(-1);
if (Convert.ToDateTime(empHiredDate).Month > 4)
{
finMonth = Convert.ToDateTime(empHiredDate).Month - 4;
finMonth = 12 - finMonth;
avail =Convert.ToString(finMonth * 1.25);
}
else if (Convert.ToDateTime(empHiredDate).Month < 3)
{
finMonth = Convert.ToDateTime(empHiredDate).Month + 8;
finMonth = 12 - finMonth;
avail = Convert.ToString(finMonth * 1.25);
}
else if (Convert.ToDateTime(empHiredDate).Month == 4)
{
avail = Convert.ToString(12 * 1.25);
}
else if (Convert.ToDateTime(empHiredDate).Month == 3)
{
avail = Convert.ToString(1 * 1.25);
}
Lets say We have two billing period for our mobile call, if we call between 0-12, then call rate is 1$/Min & if we call between 12-24, then the rate is 2$/min. A call can starts at any time & lasts for any duration. I need to calculate the bill for the call duration. I'm getting it difficult to work with the datetime type. Also I need a better algorithm to calculate the bill. I'm trying something like this:
DateTime StartTime, EndTime;
decimal Bill = 0;
decimal RemainingDuration;
StartTime = DateTime.Now;
EndTime = DateTime.Now.AddHours(2.5);
var Duration = (EndTime.ToString("H:mm") - StartTime.ToString("H:mm"));
if (StartTime.Hour > 0 && StartTime.Hour < 12)
{
//var RemainingTime = 12.00 - StartTime;
//if (Duration < RemainingTime)
//{
// Bill = (Duration * 60) * 1;
// Console.WriteLine(Bill);
//}
//else
//{
// RemainingDuration = Duration - RemainingTime;
// Bill = ((RemainingTime * 60) * 1) + ((RemainingDuration * 60) * 2);
// Console.WriteLine(Bill);
//}
}
else if (StartTime.Hour > 12 && StartTime.Hour < 24)
{
//var RemainingTime = 24.00 - StartTime.Hour;
//if (Duration < RemainingTime)
//{
// Bill = (Duration * 60) * 2;
// Console.WriteLine(Bill);
//}
//else
//{
// RemainingDuration = Duration - RemainingTime;
// Bill = ((RemainingTime * 60) * 2) + ((RemainingDuration * 60) * 1);
// Console.WriteLine(Bill);
//}
}
Console.ReadLine();
There are some errors for type miss match. the errors are not my prime concern here, I wrote this code assuming the call duration can be maximum 24 hours. I need to write it for unlimited duration. Also Getting hard time to convert types. Code sample would really help. thanks
You're getting a type mismatch since you're converting the DateTime to strings before attempting arithmetic on them. As for the algorithm, well, of course there are thousands of ways you could do it, but here is a simple example that solves your 24 hour problem and perhaps gives you some more ideas.
decimal bill = 0;
DateTime startTime = DateTime.Now;
DateTime endTime = DateTime.Now.AddHours(2.5);
DateTime timeNow = startTime;
while (timeNow <= endTime)
{
decimal rate = (timeNow.Hour >= 12 && timeNow.Hour <= 24) ? 2 : 1;
bill = bill + rate;
Console.WriteLine("{0:HH:mm}, rate: ${1:#,0.00}, bill: ${2:#,0.00}", timeNow, rate, bill);
timeNow = timeNow.AddMinutes(1);
}
Console.WriteLine("Bill: {0:HH:mm} to {1:HH:mm}, {2:#,0} mins, ${3:#,0.00}", startTime, endTime, (endTime - startTime).TotalMinutes, bill);
Console.ReadLine();
I want to calculate the count of total quarters (of a year) in the given time span.
for example:
start date = 1-june -2009
end date = 18-july-2011
count should be = 10.
one more
start date = 4-Jan-2009
end date = 27-oct -2010
count =8.
I have not been able to get the correct result.
Your example is wrong: there are only 7 quarters between 4-Jan-2009 and 27-oct -2010
You could simply add a reference to the Microsoft.VisualBasic.dll to your project and use DateDiff:
VB:
Public Shared Function getQuartersBetween(ByVal d1 As Date, ByVal d2 As Date) As Int32
Return DateDiff(DateInterval.Quarter, d1, d2)
End Function
C#:
public static int getQuartersBetween(System.DateTime d1, System.DateTime d2)
{
return Microsoft.VisualBasic.DateAndTime.DateDiff(DateInterval.Quarter, d1, d2);
}
or you could write your own implementation:
public class Quarter
{
public static long GetQuarters(DateTime dt1, DateTime dt2)
{
double d1Quarter = GetQuarter(dt1.Month);
double d2Quarter = GetQuarter(dt2.Month);
double d1 = d2Quarter - d1Quarter;
double d2 = (4 * (dt2.Year - dt1.Year));
return Round(d1 + d2);
}
private static int GetQuarter(int nMonth)
{
if (nMonth <= 3)
return 1;
if (nMonth <= 6)
return 2;
if (nMonth <= 9)
return 3;
return 4;
}
private static long Round(double dVal)
{
if (dVal >= 0)
return (long)Math.Floor(dVal);
return (long)Math.Ceiling(dVal);
}
}
or in VB.NET:
Public Class Quarter
Public Shared Function GetQuarters(ByVal dt1 As DateTime, ByVal dt2 As DateTime) As Long
Dim d1Quarter As Double = GetQuarter(dt1.Month)
Dim d2Quarter As Double = GetQuarter(dt2.Month)
Dim d1 As Double = d2Quarter - d1Quarter
Dim d2 As Double = (4 * (dt2.Year - dt1.Year))
Return Round(d1 + d2)
End Function
Private Shared Function GetQuarter(ByVal nMonth As Integer) As Integer
If nMonth <= 3 Then
Return 1
End If
If nMonth <= 6 Then
Return 2
End If
If nMonth <= 9 Then
Return 3
End If
Return 4
End Function
Private Shared Function Round(ByVal dVal As Double) As Long
If dVal >= 0 Then
Return CLng(Math.Floor(dVal))
End If
Return CLng(Math.Ceiling(dVal))
End Function
End Class
Code for you : Try below code
public static void Main()
{
//Application.Run(new XmlTreeDisplay());
int monthdiuff = monthDifference(Convert.ToDateTime("01/04/09"), Convert.ToDateTime("10/27/10"));
Console.WriteLine(monthdiuff);
int totalQuater = (monthdiuff / 3) + (monthdiuff%3);
Console.WriteLine(totalQuater);
Console.ReadLine();
}
private static int monthDifference(DateTime startDate, DateTime endDate)
{
int monthsApart = 12 * (startDate.Year - endDate.Year) + startDate.Month - endDate.Month;
return Math.Abs(monthsApart);
}
Without some code to look over I can't help you find your exact problem.
If it were me I would probably find the difference between the dates in days, then divide by number of days in a quarter (91 or so). I'm sure that C# has some kind of date parsing module that can read in the dates as a string, giving you two objects that you could then subtract to find the difference in days.
This is one crude form of calculating the quarters based on your assumptions, you can choose to modify as it is it works good enough
DateTime dt1 = new DateTime(2009, 1, 1);// new DateTime(2009, 6, 1);
DateTime dt2 = new DateTime(2010, 10, 27);// new DateTime(2011, 7, 18);
if (dt1.Month < 4)
dt1 = new DateTime(dt1.Year,1,1);
else if (dt1.Month < 7)
dt1 = new DateTime(dt1.Year,4,1);
else if (dt1.Month < 10)
dt1 = new DateTime(dt1.Year,7,1);
else
dt1 = new DateTime(dt1.Year,10,1);
if (dt2.Month < 4)
dt2 = new DateTime(dt2.Year, 3, DateTime.DaysInMonth(dt2.Year, 3));
else if (dt2.Month < 7)
dt2 = new DateTime(dt2.Year, 6, DateTime.DaysInMonth(dt2.Year, 6));
else if (dt2.Month < 10)
dt2 = new DateTime(dt2.Year, 9, DateTime.DaysInMonth(dt2.Year, 9));
else
dt2 = new DateTime(dt2.Year, 12, DateTime.DaysInMonth(dt2.Year, 12));
TimeSpan ts = dt2 - dt1;
int quarters = (int) ts.TotalDays/90;
Console.WriteLine(quarters);
I am baselining the dates to the start and end of the quarters as you want and then assuming for 90 day quarter transforming the diff as int. Works for your mentioned examples,see if it suits you well enough
If the definition of a quarter is a 90-day difference, it's easy of course:
internal static int GetNumberOfQuarters(DateTime p_DtStart, DateTime p_DtEnd)
{
TimeSpan span = p_DtEnd.Subtract(p_DtStart);
return (int)span.TotalDays % 90;
}
But that's not what you're looking for. What about this (not tested but you'll get the idea)
internal static class DateTimeTools
{
internal static int GetNumberOfQuartersBetweenDates(DateTime startDate, DateTime endDate)
{
int iYearStart, iYearEnd, iMonthStart, iMonthEnd, iDayStart, iDayEnd;
iYearStart = startDate.Year;
iYearEnd = endDate.Year;
iMonthStart = startDate.Month;
iMonthEnd = endDate.Month;
iDayStart = startDate.Day;
iDayEnd = endDate.Day;
int iYearDiff, iQuarterDiff, iDayDiff;
iYearDiff = iYearEnd - iYearStart;
iQuarterDiff = iMonthEnd % 3 - iMonthStart % 3;
iDayDiff = iDayEnd - iDayStart;
int iNumOfQuarters = 0;
// at least a year difference?
if ((iYearDiff > 0 && iQuarterDiff > 0) || iYearDiff > 0 && iQuarterDiff == 0 && iDayDiff >= 0)
{
iNumOfQuarters = iYearDiff * 4 + iQuarterDiff;
}
// at least a quarter difference?
// within different years
if ((iYearDiff > 0 && iQuarterDiff <= 0)) // eg, dec 2010 - feb 2011 iYearDiff 1 iQuarterDiff -3
{
if ((iQuarterDiff == -3 && iDayDiff >= 0) || iQuarterDiff > -3)
{
iNumOfQuarters = iQuarterDiff + 4;
}
}
// within the same year
if (iYearDiff == 0 && iQuarterDiff > 0)
{
if ((iQuarterDiff == 1 && iDayDiff >= 0) || iQuarterDiff > 1)
{
iNumOfQuarters = iQuarterDiff;
}
}
return iNumOfQuarters;
}
}
Regards,
Nico
public static string GetQuarter(this DateTime date)
{
var quarterList = new List<string>();
if (date.Month >= 1 && date.Month <= 3)
return "Q1";
else if (date.Month >= 4 && date.Month <= 6)
return "Q1,Q2";
else if (date.Month >= 7 && date.Month <= 9)
return "Q1,Q2,Q3";
else
return "Q1,Q2,Q3,Q4";
}
This too can be used as an extension method if you are expecting to get a list of Quarters, You can later on use GetQuarter().Split(new[] { ',' }).Count() to get the count.
Easy formula to get quarters difference:
{
int firstQuarter = getQuarter(first);
int secondQuarter = getQuarter(second);
return 1 + Math.Abs(firstQuarter - secondQuarter);
}
private static int getQuarter(DateTime date)
{
return (date.Year * 4) + ((date.Month - 1) / 3);
}