假设财务季度始终在一个月的第一天开始,并且总是3个日历月。
不同的组织在不同月份开始其财政年度(FY) - 有些可能是4月1日,有些可能是7月1日,或者可能只是1月1日(这将与正常的日历季度相匹配)。
考虑到FY开始的日期和月份,您如何确定该日期所在季度的开始。
E.g。
DateTime getStartOfFinancialQtr(DateTime date, int monthFinancialYearStartsOn)
1月15日,当FY开始Jan将= 1月1日
getStartOfFinancialQtr(new DateTime(2013,1,15), 1) == new DateTime(2013,1,1)
8月15日,FY将于4月1日开始,
getStartOfFinancialQtr(new DateTime(2013,8,15), 4) == new DateTime(2013,7,1)
但2013年1月15日,2月开始2月将是11月1日 2012
getStartOfFinancialQtr(new DateTime(2013,1,15), 2) == new DateTime(2012,11,1)
答案 0 :(得分:6)
以下解决方案是我能想到的最简单的实现,并且没有任何 - 不必要的循环:
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);
}
答案 1 :(得分:3)
这不简单吗?我错过了什么吗?四分之一被定义为三个月的期间,因此您只需要找到给定日期的位置,然后根据该日期的给定月份计算季度开始的位置。
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;
}
以下是我跑的测试:
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());
控制台输出:
01/01/2013 000000
07/01/2013 000000
11/01/2012 000000
答案 2 :(得分:3)
您可以使用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
答案 3 :(得分:1)
如上所述,您可以轻松从Nearest Completed quarter获取答案。以下是您进行修改的方式:
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;
}
}
}
用法:
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));
输出:
1/1/2013 12:00:00 AM
7/1/2013 12:00:00 AM
11/1/2012 12:00:00 AM
这会传递所有三个测试用例。