+-
java – 如何使用joda-time代表“每个季度的第一个月”?
我正在研究一些会计逻辑.逻辑是,在一个季度的第一个月发生的会计必须具有在上一个季度末的价值日期.我知道我可以将月份表示为一个时期.但我不知道如何代表四分之一年的经常性时期.

我能够使用joda-time类进行计算,这将给出上一季度末的价值日期.但是,我想将“每个季度的第一个月”表示为我在计算中使用的单个值.

那么在joda-time中是否有一些API非常适合代表这种反复出现的时期?

一些示例日期是:

date of invoce | value date  
2013-01-01     | 2012-12-31  
2013-01-31     | 2012-12-31  
2013-02-01     | 2013-02-01  
2013-03-31     | 2013-03-31  
2013-04-01     | 2013-03-31 

好的,这里是评论中要求的更具说明性的例子:
会计逻辑是关于您必须申请的一种养老基金.您在接下来的一年,即2013年1月1日申请2012年的退休金.它将在2013年4月15日授予您.自4月是本季度的第一个月,授予将具有其价值日期定于3月31日.所有在一个季度内计入的养老金都在该季度结束后的1个月和5天内支付.因此,即使您在4月份获得了养老金,您仍然可以在5月5日获得养老金.否则你将不得不等到9月5日之前付款.

但我真的不知道这个例子应该如何帮助.这个问题实际上是关于使用joda-time类建模“每个季度的每个第一个月”,甚至是实施一些joda-time的API.

最佳答案
算法

您需要编写一个例程,在该例程中传递日期并返回表示上一季度最后一天的日期.实际上,这听起来像是方法的一个好名字,以及对问题的更好总结:endingDateOfPreviousQuarter(someDate).

或者在我自己的命名约定中命名,我使用start和stop来表示包容性而非排他性边界,stopDateOfPreviousQuarter(someDate).

我会用一对方法做到这一点.

startDateOfQuarter(someDate)

>通过调用monthOfYear()提取传递日期的月份.
>确定哪个季度是那个月(测试在1-3,4-6,7-9,9-12之间).
>获取该季度的开始日期(如下面的代码所示,将年和月以及dayOfMonth传递给构造函数).

stopDateOfPreviousQuarter(someDate)

>调用“startDateOfQuarter”方法,传递相关日期.
>在返回的开始日期,调用Joda-Time方法minusDays(1).

Voilà,您有上一季度最后一天的日期.

这里的主要思想是,通常最好找到一个时间元素的开头,然后使用减号,而不是试图直接获得结束点.获取一小时,一天,一周,一个月或一个季度的开头.这避免了闰日,闰秒†,Daylight Saving Time(DST)的问题,记住哪个月有30对31天的错误,以及具有不同分辨率的小数秒的问题使得难以确定一小时或一天的结束.此外,至少在我的经验中,关注时期的开始可以清晰地思考日期时间.

信息

ISO 8601不承认宿舍.有些人使用“Q”和一些标识符来扩展规范,如this wiki所述.

Joda-Time 2不支持季度,如2011年this discussion所述.

ISO 8601精确定义了52或53 numbered weeks.Joda-Time支持这一概念,由weekOfWeekYear表示.一些企业通过1至52/53范围的子集来定义其宿舍.

或者您可以在一年的第3个月,第6个月,第9个月和第12个月结束时定义您的宿舍. Joda-Time具有DateTime类的构造函数,可用于指定月份编号.请注意使用方法withTimeAtStartOfDay()让Joda-Time完成当天第一时刻的工作,因为并非所有时区的所有日子都有午夜.

org.joda.time.DateTimeZone parisDateTimeZone = org.joda.time.DateTimeZone.forID( "Europe/Paris" );
org.joda.time.DateTime q1Start =  new org.joda.time.DateTime(2013, 1, 1, 0, 0, parisDateTimeZone ).withTimeAtStartOfDay();
org.joda.time.DateTime q2Start =  new org.joda.time.DateTime(2013, 4, 1, 0, 0, parisDateTimeZone ).withTimeAtStartOfDay();

System.out.println( "Q1 begins in Paris FR: " + q1Start );
System.out.println( "Q2 begins in Paris FR: " + q2Start );

// When querying a database or comparing items in a collection to find Q1 data, 
// Look for: (GreaterThanOrEqualTo q1Start) AND (LessThan q2Start)

如果您绝对只想要日期而没有任何时间元素,请使用Joda-Time的LocalDate课程.该课程像DateTime课程一样运动minusDays()方法.

顺便说一下,考虑一下你是处理简单日期(没有时间)还是日期时间.例如,您可能会认为发票仅使用简单的日期,但实际上它们通常在收到时使用时钟机器盖章,其中包括可能因法律和审计原因需要记录的时间.此外,通常数据库将日期值存储为基于UTC的日期时间(没有时区偏移).

†Joda-Time忽略了leap-seconds,但我的观点仍然存在.

点击查看更多相关文章

转载注明原文:java – 如何使用joda-time代表“每个季度的第一个月”? - 乐贴网