I would like to calculate the last half-year starting from the today in c#.
A first half-year in my scenario is 01/01/ - 06/30/.
A second half-year in my scenario is 07/01/ - 12/31/.
How would you calculate this using DateTime?
Example: Today is 03/15/2014 -> last half-year: 07/01/2013 - 12/31/2013
Example: Today is 07/15/2014 -> last half-year: 01/01/2014 - 06/30/2014.
Thanks in advance! ;-)
You only have to look at the month from 6 months ago, and determine the half it is in:
DateTime start, end;
var date = DateTime.Today.AddMonths(-6);
var month = date.Month;
var year = date.Year;
if (month <= 6) {
start = new DateTime(year, 1, 1);
end = new DateTime(year, 6, 30);
} else {
start = new DateTime(year, 7, 1);
end = new DateTime(year, 12, 31);
}
Just have an if else where you check if month is greater than 6 and create date range as below.
DateTime today = DateTime.Today;
if(today.Month > 6)
Console.WriteLine(new DateTime(today.Year,1,1).ToShortDateString() + "->" +
new DateTime(today.Year,6,30).ToShortDateString());
else
Console.WriteLine(new DateTime(today.Year-1,6,1).ToShortDateString() + "->" +
new DateTime(today.Year-1,12,31).ToShortDateString());
You can do this:
var start = new DateTime(
DateTime.Today.Year,
1 + 6 * (DateTime.Today.Month / 7),
1);
var end = new DateTime(
DateTime.Today.Year + DateTime.Today.Month / 7,
7 - 6 * (DateTime.Today.Month / 7),
1).AddDays(-1.0);
Step back by one day until you hit either Month 12 or Month 06
// get first of this month
DateTime prev = new DAteTime( DateTime.Today.Year, DateTime.Today.Month, 1);
bool found = false;
while(found == false){
prev = prev.AddDays(-1);
if(prev.Month == 12)
found = true;
if(prev.Month == 6)
found = true
}
// then when found, count back 6 months from that
DateTime start = prev.AddMonths(-6)
// then get the first of that month
start = new DateTime(start.Year, start.Month, 1);
Please find the below snippet.
string firstHalf = "30/06/";
int currentYear = DateTime.Now.Date.Year;
if (DateTime.Now.Date > Convert.ToDateTime(firstHalf + Convert.ToString(currentYear)).Date)
{
MessageBox.Show("Last Half Year : " + "01/01/" + Convert.ToString(currentYear) + " to 30/06/" + Convert.ToString(currentYear));
}
else
MessageBox.Show("Last Half Year : " + "01/07/" + Convert.ToString(currentYear - 1) + " to 31/12/" + Convert.ToString(currentYear - 1));
Thanks to you guys. I prefer the answer of GvS.
I was doing this:
var halfyear = (float)DateTime.Today.Month / 6;
var halfyearModulo = halfyear % 1;
if (halfyearModulo == 0)
halfyear--;
var minimumDate = new DateTime(DateTime.Today.Year, ((int)halfyear * 6) + 1, 1).AddMonths(-6);
var maximumDate = minimumDate.AddMonths(6);
But i think GvSs anwser is way better.
Related
What would be the easiest way for me to assign my quarter end month based upon the month im in?
Is there something i can use like modulo? I want the simplest case and least amount of lines of code
My quarter ends months are months 3,6,9 and 12.
I want to avoid doing a logic like this:
if (1 <= mymonth && mymonth <= 3)
mymonth = new DateTime(DateTime.Now.Year, 3, 15);
else if (4 <= mymonth && mymonth <= 6)
mymonth = new DateTime(DateTime.Now.Year, 6, 15);
else if (7 <= mymonth && mymonth <= 9)
mymonth = new DateTime(DateTime.Now.Year, 9, 15);
else
mymonth = new DateTime(DateTime.Now.Year, 12, 15);
You can use:
var quarterEndMonth = 3 * Math.Ceiling((double)currentMonth / 3);
Demonstration
What about this?
public DateTime GetQuarterEnd(int month)
{
if (month < 1 || month > 12)
throw new ArgumentException("month is not a valid Month of the year.");
var mod = month % 3;
var actual = month / 3 + (mod > 0 ? 1 : 0);
return new DateTime(DateTime.Now.Year, actual * 3, 15);
}
Least amount of lines could be something like this:
var d = new DateTime(DateTime.Now.Year, 3*(1+(mymonth-1)/3), 15);
But that is ugly as hell :)
https://dotnetfiddle.net/HZfFLF
I have been using a C# function to get the month of week and I need a similar function in T-SQL to get the same result.
public static int GetWeekNumberOfMonth(DateTime date)
{
date = date.Date;
DateTime firstMonthDay = new DateTime(date.Year, date.Month, 1);
var mon = (int)DayOfWeek.Monday;
var dofw = (int)firstMonthDay.DayOfWeek;
DateTime firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
if (firstMonthMonday > date)
{
firstMonthDay = firstMonthDay.AddMonths(-1);
firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
}
return (date - firstMonthMonday).Days / 7 + 1;
}
Try like this:
DECLARE #d DATETIME
SET #d = '2015-10-20'
SELECT DATEPART(WEEK, #d) -
DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,#d), 0))+ 1 AS WEEK_OF_MONTH
My code below.I want to do user select 10.06.2015 09:00 - 12.06.2015 13:00 after I will show 2 days 2 hours.
But I want to do Working days and Working Hours beetween 09:00 - 18:00 well users when you 10.06.2015 09:00 - 12.06.2015 13:00 I want to show only 2,5 days.
How can I do?
DateTime t1 = dateTimePicker1.Value.Date;
DateTime t2 = dateTimePicker2.Value.Date;
string s1 = textBox9.Text;
string s2 = textBox10.Text;
DateTime dt1 = t1.AddMinutes(DateTime.Parse(s1).TimeOfDay.TotalMinutes);
DateTime dt2 = t2.AddMinutes(DateTime.Parse(s2).TimeOfDay.TotalMinutes);
var fark = dt2 - dt1;
label1.Text =
String.Format("{0}{1}{2}",
fark.Days > 0 ? string.Format("{0} gün", fark.Days) : "",
fark.Hours > 0 ? string.Format("{0} saat ", fark.Hours) : "",
fark.Minutes > 0 ? string.Format("{0} dakika ", fark.Minutes) : "").Trim();
Well you can assume that any days in the range, except the first and last are full working days. So you need (AllDaysInRange -2) + HoursInfirstDay + HoursInLastDay.
TimeSpan ts = t2 - t1;
ts.Days = ts.Days - 2; //Allow for the 2 end days
int Day1Hours = t1.Hours - 9;//This removes any hours between 00.00 and 09.00
if (day1Hours > 9) //Then the user was working past 18.00
ts.Days = ts.Days+1
else
ts.Hours = ts.Hours + day1Hours;
int Day2Hours = t2.Hours - 9;//This removes any hours between 00.00 and 09.00
if (day2Hours > 9) //Then the user was working past 18.00
ts.Days = ts.Days+1
else
ts.Hours = ts.Hours + day2Hours;
If you can get this to work (I have written it from memory), then I'd wrap the code to convert the hours of the end days into a method rather than repeating it.
According to DateTime Picker In WinForm How To Pick Time? post, you can change your DateTimePicker, to function with times as well.
To limit the range which the users can select, you can modify your ValueChanged event or write your own validation for it.
Probably the simplest is:
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
if (dateTimePicker1.Value.Hour < 10) // the 10 is just a random number, you can change it to your own limit
dateTimePicker1.Value = this.dateTimePicker1.Value.AddHours(10 - dateTimePicker1.Value.Hour);
}
To calculate your 2,5 day according to the working hours, i would write a function to handle this responsibility like:
private int TimeInWorkingHours(DateTime start, DateTime end, int firstHour, int lastHour)
{
int days = Math.Min(end.Subtract(start).Days - 2, 0) ;
int hoursInADay = lastHour - firstHour;
int result = days * hoursInADay;
result += start.Hour - firstHour;
result += lastHour - end.Hour;
return result;
}
This way you call TimeInWorkingHours(...) function with your start date and end date, also providing your first and last working hours.
First you calculate the worked days, than add the border hours. This way you get your worked hours which you can then divide by the work hours to get your working days.
try this
private void GetProperOfficeHours(ref DateTime date)
{
int minHour = 9, maxHour = 17;
if (date.Hour < minHour) //if earlier than office hours - start from 9am
{
date = date + new TimeSpan(9, 0, 0);
}
else if (date.Hour > maxHour) //if later than office hours - go to next day 9am
{
date = date.AddDays(1) + new TimeSpan(9, 0, 0);
}
}
Then ...
//assuming firstDate & lastDate have date and time
int[] weekendDays = new int[2] { 0, 6 }; // Sunday and Saturday
GetProperOfficeHours(ref firstDate);
GetProperOfficeHours(ref lastDate);
while (weekendDays.Contains((int)firstDate.DayOfWeek))
{
//get next date
firstDate = firstDate.AddDays(1);
}
while (weekendDays.Contains((int)lastDate.DayOfWeek))
{
//get prev date
lastDate = lastDate.AddDays(-1);
}
double hourDiff = Math.Abs(firstDate.Hour - lastDate.Hour) / 8.0; //8 office hours
double dayDifference = 0;
while (firstDate.Date <= lastDate.Date) //Loop and skip weekends
{
if (!weekendDays.Contains((int)firstDate.DayOfWeek)) //can also check for holidays here
dayDifference++;
firstDate = firstDate.AddDays(1);
}
dayDifference = dayDifference + hourDiff;
May need some tweaking, hope you find it helpful.
Try this
bool IsWorkingDay(DateTime dt)
{
int year = dt.Year;
Dictionary<DateTime, object> holidays = new Dictionary<DateTime, object>();
holidays.Add(new DateTime(year, 1, 1), null);
holidays.Add(new DateTime(year, 1, 6), null);
holidays.Add(new DateTime(year, 4, 25), null);
holidays.Add(new DateTime(year, 5, 1), null);
holidays.Add(new DateTime(year, 6, 2), null);
holidays.Add(new DateTime(year, 8, 15), null);
holidays.Add(new DateTime(year, 11, 1), null);
holidays.Add(new DateTime(year, 12, 8), null);
holidays.Add(new DateTime(year, 12, 25), null);
holidays.Add(new DateTime(year, 12, 26), null);
DateTime easterMonday = EasterSunday(year).AddDays(1);
if (!holidays.ContainsKey(easterMonday))
holidays.Add(easterMonday, null);
if (!holidays.ContainsKey(dt.Date))
if (dt.DayOfWeek > DayOfWeek.Sunday && dt.DayOfWeek < DayOfWeek.Saturday)
return true;
return false;
}
string WorkingTime(DateTime dt1, DateTime dt2)
{
// Adjust begin datetime
if (IsWorkingDay(dt1))
{
if (dt1.TimeOfDay < TimeSpan.FromHours(9))
dt1 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 9, 0, 0);
else if (dt1.TimeOfDay > TimeSpan.FromHours(13) && dt1.TimeOfDay < TimeSpan.FromHours(14))
dt1 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 14, 0, 0);
else if (dt1.TimeOfDay > TimeSpan.FromHours(18))
dt1 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 9, 0, 0).AddDays(1);
}
else
dt1 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 9, 0, 0).AddDays(1);
// Adjust end datetime
if (IsWorkingDay(dt2))
{
if (dt2.TimeOfDay < TimeSpan.FromHours(9))
dt2 = new DateTime(dt2.Year, dt2.Month, dt2.Day, 18, 0, 0).AddDays(-1);
else if (dt2.TimeOfDay > TimeSpan.FromHours(18))
dt2 = new DateTime(dt2.Year, dt2.Month, dt2.Day, 18, 0, 0);
else if (dt2.TimeOfDay > TimeSpan.FromHours(13) && dt2.TimeOfDay < TimeSpan.FromHours(14))
dt2 = new DateTime(dt2.Year, dt2.Month, dt2.Day, 13, 0, 0);
}
else
dt2 = new DateTime(dt2.Year, dt2.Month, dt2.Day, 18, 0, 0).AddDays(-1);
double days = 0;
double hours = 0;
double minutes = 0;
if (dt2 > dt1)
{
// Move dt1 forward to reach dt2 day chacking for working days
while (dt1.DayOfYear < dt2.DayOfYear)
{
if (IsWorkingDay(dt1))
days++;
dt1 = dt1.AddDays(1);
}
// Now get the worked hours as if were on the same day in the same manner
TimeSpan sdwt = dt2 - dt1;
if (dt1.TimeOfDay < TimeSpan.FromHours(13) && dt2.TimeOfDay > TimeSpan.FromHours(14))
sdwt -= TimeSpan.FromHours(1);
if (sdwt == TimeSpan.FromHours(8))
days++;
else
{
hours = sdwt.Hours;
minutes = sdwt.Minutes;
}
}
// There is a pause in between so adjust if the interval include it
var totalminutes = (days * 8 * 60 + hours * 60 + minutes);
string res = String.Format("{0} days {1} hours {2} minutes",
days,
hours,
minutes);
string totRes = String.Format("{0} days {1} hours {2} minutes",
totalminutes / 8 / 60,
totalminutes / 8,
totalminutes);
return res + "\r\n" + totRes;
}
Assume Financial Quarters always start on the 1st of a month and they are always 3 calendar months long.
Different organisations start their Financial Year (FY) in different months - some may be 1st April , some may be 1st July or could be just 1st Jan (which will match normal Calendar Quarters).
Given a date and a month that the FY starts on how can you determine the start of the quarter that the date falls in.
E.g.
DateTime getStartOfFinancialQtr(DateTime date, int monthFinancialYearStartsOn)
15th Jan when FY starts Jan would = 1st Jan
getStartOfFinancialQtr(new DateTime(2013,1,15), 1) == new DateTime(2013,1,1)
15th August when FY starts April would be 1st July
getStartOfFinancialQtr(new DateTime(2013,8,15), 4) == new DateTime(2013,7,1)
BUT 15th Jan 2013 when FY starts February would be 1st November 2012
getStartOfFinancialQtr(new DateTime(2013,1,15), 2) == new DateTime(2012,11,1)
The following solution is the most simple implementation I could think of and works without any - unnecessary - loops:
DateTime getStartOfFinancialQtr(DateTime date, int monthFinancialYearStartsOn)
{
var actualMonth = date.Month;
var financialYear = date.Year;
var difference = actualMonth - monthFinancialYearStartsOn;
if(difference < 0)
{
--financialYear;
difference += 12;
}
var quarter = difference / 3;
return new DateTime(financialYear, monthFinancialYearStartsOn, 1).AddMonths(quarter * 3);
}
Isn't it as simple as this? Am I missing something to this? A quarter is defined as a period of three months, so you just have to find where the given date is, and then compute where the quarter begins based off that given month of the date.
public DateTime GetStartOfFinancialQtr(DateTime dtGiven, int startMonth) {
DateTime dtQuarter = new DateTime(dtGiven.Year, startMonth, 1);
// Start Q is less than the given date
if(startMonth > dtGiven.Month) {
while(dtQuarter > dtGiven) {
dtQuarter = dtQuarter.AddMonths(-3);
}
}
// Start Q is larger than the given date
else {
while(dtQuarter.Month + 3 <= dtGiven.Month) {
dtQuarter = dtQuarter.AddMonths(3);
}
}
return dtQuarter;
}
Below is the testing I ran:
Console.WriteLine(GetStartOfFinancialQtr(new DateTime(2013, 1, 15), 1).ToString());
Console.WriteLine(GetStartOfFinancialQtr(new DateTime(2013, 8, 15), 4).ToString());
Console.WriteLine(GetStartOfFinancialQtr(new DateTime(2013, 1, 15), 2).ToString());
Console output:
01/01/2013 000000
07/01/2013 000000
11/01/2012 000000
You can use the Year class of the Time Period Library for .NET:
// ----------------------------------------------------------------------
public void FiscalYearRange()
{
// calendar
TimeCalendar fiscalYearCalendar = new TimeCalendar(
new TimeCalendarConfig
{
YearBaseMonth = YearMonth.April,
YearType = YearType.FiscalYear
} );
// time range
TimeRange timeRange = new TimeRange( new DateTime( 2007, 10, 1 ), new DateTime( 2012, 2, 25 ) );
Console.WriteLine( "Time range: " + timeRange );
Console.WriteLine();
// fiscal quarter
Console.WriteLine( "Start Quarter: " + new Quarter( timeRange.Start, fiscalYearCalendar ) );
Console.WriteLine( "End Quarter: " + new Quarter( timeRange.End, fiscalYearCalendar ) );
Console.WriteLine();
// fiscal year
Year year = new Year( timeRange.Start, fiscalYearCalendar );
while ( year.Start < timeRange.End )
{
Console.WriteLine( "Fiscal Year: " + year );
year = year.GetNextYear();
}
} // FiscalYearRange
As mentioned, you can easily obtain the answer from Nearest Completed quarter. Here's how you make the modification:
public static class DateTimeExtensions {
public static DateTime NearestQuarterEnd(
this DateTime date,
int firstMonthOfFiscalYear
) {
IEnumerable<DateTime> candidates =
QuartersInYear(date.Year, firstMonthOfFiscalYear)
.Concat(QuartersInYear(date.Year - 1, firstMonthOfFiscalYear));
return candidates.SkipWhile(d => d > date).First();
}
static Dictionary<Tuple<int, int>, List<DateTime>> dict =
new Dictionary<Tuple<int, int>, List<DateTime>>();
static IEnumerable<DateTime> QuartersInYear(
int year,
int firstMonthOfFiscalYear
) {
Contract.Requires(firstMonthOfFiscalYear >= 1
&& firstMonthOfFiscalYear <= 12);
var key = Tuple.Create(year, firstMonthOfFiscalYear);
if(dict.ContainsKey(key)) {
return dict[key];
}
else {
var value =
Enumerable
.Range(0, 4)
.Select(k => firstMonthOfFiscalYear + 3 * k)
.Select(m => m <= 12 ? m : m % 12)
.Select(m => new DateTime(year, m, 1))
.OrderByDescending(d => d)
.ToList();
dict.Add(key, value);
return value;
}
}
}
Usage:
Console.WriteLine(new DateTime(2013, 1, 15).NearestQuarterEnd(1));
Console.WriteLine(new DateTime(2013, 8, 15).NearestQuarterEnd(4));
Console.WriteLine(new DateTime(2013, 1, 15).NearestQuarterEnd(2));
Output:
1/1/2013 12:00:00 AM
7/1/2013 12:00:00 AM
11/1/2012 12:00:00 AM
This passes all three of your test cases.
I need help finding the second Wednesday of the year. Here is what I have done, but it doesn't seem to work.
DateTime baseDay = new DateTime(DateTime.Now.Year, 1, 5);
int secondWed = 5 + ((12 - (int)baseDay.DayOfWeek) % 7);
DateTime fullDate = new DateTime(DateTime.Now.Year, 1, secondWed);
Try this method instead:
DateTime dt = new DateTime(DateTime.Now.Year, 1, 8); //get second week of the year
while(dt.DayOfWeek != DayOfWeek.Wednesday) //loop until we find the next Wednesday
dt = dt.AddDays(1);
Based on the very good answer by Mark Ransom to How to find the 3rd Friday in a month with C#?. There is no looping here.
var year = 2011;
var firstDayOfMonth = new DateTime(year, 1, 1);
var daysUntilNextWednesday = DayOfWeek.Wednesday - firstDayOfMonth.DayOfWeek;
if (daysUntilNextWednesday < 0)
daysUntilNextWednesday += 7;
var firstWednesdayOfMonth = firstDayOfMonth.AddDays(daysUntilNextWednesday);
var secondWednesdayOfMonth = firstWednesdayOfMonth.AddDays(7);
You can merge the last two lines into one for slightly better performance.
May be this helps
DateTime startDate = new DateTime(DateTime.Now.Year, 1, 1);
int c = (int)startDate.DayOfWeek;
int n = (int)DayOfWeek.Wednesday;
int weekcount=2;
int diff = (7 - c + n);
int days= (diff > 7) ? diff % 7 : diff;
startDate.AddDays((weekcount-1)*7+ days );
Something this simple would also work...
int weekNumber = 2;
DateTime seekingDate = new DateTime(DateTime.Now.Year, 1, 1);
while (seekingDate.DayOfWeek != DayOfWeek.Wednesday)
seekingDate = seekingDate.AddDays(1);
seekingDate.AddDays(7 * (weekNumber - 1));
Of course, I would use variable for the weekday and the week number.
I believe this would also work:
var date = new DateTime(DateTime.Now.Year,1,1);
if(date.DayOfWeek > DayOfWeek.Tuesday)
date = date.AddDays(9 - (int)date.DayOfWeek);
else if(date.DayOfWeek < DayOfWeek.Tuesday)
date = date.AddDays(2 - (int)date.DayOfWeek);
date = date.AddDays(7);