首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用joda时间来表示“每个季度的第一个月”?

如何使用joda时间来表示“每个季度的第一个月”?
EN

Stack Overflow用户
提问于 2013-11-12 07:19:18
回答 2查看 4.4K关注 0票数 4

我在研究一些会计逻辑。其逻辑是,在第一个季度的第一个月发生的会计必须有一个价值日期是在前一个季度的年底。我知道我可以把这个月作为一个时期来表示。但我不知道如何代表一个季度的经常性周期。

我能够使用joda时间类进行计算,这将给出上一季度末的值日期。不过,我想把“每个季度的第一个月”作为我计算时使用的单一数值。

那么,在joda时间中是否有一些API可以很好地表示这种循环周期呢?

一些例子日期是:

代码语言:javascript
复制
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时间类来建模“每个季度的第一个月”,甚至是实现joda-time的一些API。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-12 08:05:43

算法

你需要写一个例程,在那里你传递一个日期,并得到一个日期代表前一个季度的最后一天。实际上,这听起来是该方法的一个好名称,也是对您的问题的更好的总结:endingDateOfPreviousQuarter( someDate )

或者,在我自己的命名约定中,我使用startstop来表示包含而不是排他的边界,stopDateOfPreviousQuarter( someDate )

我会用两种方法来做到这一点。

startDateOfQuarter( someDate )

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

stopDateOfPreviousQuarter( someDate )

  1. 调用"startDateOfQuarter“方法,传递有关日期。
  2. 在返回的开始日期,调用Joda-Time方法minusDays(1)

哇,你有前一季度最后一天的日期。

这里的主要思想是,通常情况下,最好找到时间元素的开头,然后使用minus,而不是直接获取结束点。得到一个小时、一天、一周、一个月或一个季度的开始。这避免了闰日、闰秒夏令时、DST、记住哪个月有30天和31天的错误,以及分辨率不同的分数秒问题,从而很难确定一小时或一天的结束时间。此外,专注于周期的开始,至少在我的经验中,能让我清晰地思考日期的时间。

信息

ISO 8601不认识四分之一。有些人通过使用"Q“和一些标识符(如这个维基中提到的)来扩展规范。

Joda-时间2不支持季度,正如这一讨论在2011年提到的那样。

ISO 8601精确定义了52或53 数周的定义。Joda-Time支持这个由weekOfWeekYear所代表的概念。一些企业根据1到52/53区间的一个子集来定义自己的季度。

或者你可以在一年中的第3、6、9和12个月结束前定义你的宿舍。Joda-Time有DateTime类的构造函数,它允许您指定一个月号。请注意,使用withTimeAtStartOfDay()方法可以让Joda-Time完成获取一天中第一分钟的工作,因为并非所有时区中的所有日子都有午夜。

代码语言:javascript
复制
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类。该类使用minusDays()方法,就像DateTime类一样。

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

闰秒时间忽略了†,但我的观点仍然站得住脚。

票数 5
EN

Stack Overflow用户

发布于 2014-06-08 10:55:32

我也必须实现这一点。下面是一个乍一看似乎没问题的实现。

代码语言:javascript
复制
public class QuarterPeriods {

    public static LocalDate quarterStartFor(LocalDate date) {
        return date.withDayOfMonth(1).withMonthOfYear((((date.getMonthOfYear() - 1) / 3) * 3) + 1);
    }

    public static LocalDate quarterEndFor(LocalDate date) {
        return quarterStartFor(date).plusMonths(3).minusDays(1);
    }
}

public class QuarterPeriodsTest {

    @Test
    public void startOfQuarter() throws Exception {
        assertThat(quarterStartFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/01/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/01/01")), equalTo(StubDates.dateOf("2011/01/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/01/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/04/01")), equalTo(StubDates.dateOf("2011/04/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/07/01")), equalTo(StubDates.dateOf("2011/07/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/12/19")), equalTo(StubDates.dateOf("2011/10/01")));
    }

    @Test
    public void endOfQuarter() throws Exception {
        assertThat(quarterEndFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/03/31")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/01/01")), equalTo(StubDates.dateOf("2011/03/31")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/03/31")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/04/01")), equalTo(StubDates.dateOf("2011/06/30")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/07/01")), equalTo(StubDates.dateOf("2011/09/30")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/12/19")), equalTo(StubDates.dateOf("2011/12/31")));
    }
}

public class StubDates {

    public static LocalDate dateOf(String date) {
        return DateTimeFormat.forPattern("yyyy/MM/dd").withZone(DateTimeZone.UTC).parseDateTime(date).toLocalDate();
    }
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19923162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档