4

私はいくつかの会計ロジックに取り組んでいます。ロジックは、四半期の最初の月に発生した会計の起算日は、前の四半期の年末でなければならないというものです。月を期間として表すことができることを知っています。しかし、四半期の繰り返し期間を表す方法がわかりません。

私は、前の四半期の終わりに起算日を教えてくれる 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 

OK、コメントで要求されたより説明的な例を次に示します。会計ロジックは、申請する必要がある一種の年金基金に関するものです。翌年の 2013 年 1 月 1 日に 2012 年の年金を申請します。2013 年 4 月 15 日に付与されます。4 月は四半期の最初の月であるため、付与にはその起算日があります。 3月31日に決定。四半期年内に会計処理されるすべての年金は、その四半期年が終了してから 1 か月と 5 日後に支払われます。4月に年金を受け取ったとしても、5月5日には年金が支払われます。それ以外の場合は、9 月 5 日まで支払いを待つ必要があります。

しかし、この例がどのように役立つかはよくわかりません。この質問は、「各四半期の最初の月ごと」を joda-time クラスでモデル化すること、または joda-time の API を実装することについてです。

4

2 に答える 2

5

アルゴリズム

日付を渡して前四半期の最終日を表す日付を取得するルーチンを作成する必要があります。確かに、それはメソッドの良い名前のように聞こえ、問題のより良い要約です: endingDateOfPreviousQuarter( someDate ).

または、排他的境界ではなく包括的な境界を意味するstartとを使用する独自の命名規則で、代わりに名前を付けます。stopstopDateOfPreviousQuarter( someDate )

私はそれを一対の方法で行います。

startDateOfQuarter( someDate )

  1. monthOfYear()を呼び出して、渡された日付の月を抽出します。
  2. その月がどの四半期かを判断します (1 ~ 3、4 ~ 6、7 ~ 9、9 ~ 12 の間であるかどうかをテストします)。
  3. その四半期の開始日を取得します (以下のコードに示すように、コンストラクターに year & month & dayOfMonth を渡します)。

stopDateOfPreviousQuarter( someDate )

  1. 「startDateOfQuarter」メソッドを呼び出して、問題の日付を渡します。
  2. 返された開始日に、Joda-Time のメソッドminusDays(1)を呼び出します。

ほら、前四半期の最終日の日付があります。

ここでの主な考え方は、一般に、終了点を直接取得しようとするよりも、時間要素 の開始点を見つけてから を使用する方がよいということです。minus時間、日、週、月、または四半期の始まりを取得します。これにより、うるう日、うるう秒†、夏時間(DST) の問題、どの月が 30 日か 31 日かを記憶する際のエラー、および 1 時間の終わりまたは 1 時間の終わりを判断するのが困難になるさまざまな解像度の小数秒の問題が回避されます。日。さらに、少なくとも私の経験では、期間の始まりに焦点を当てることで、日時についての考え方が明確になります。

情報

ISO 8601は四半期を認識しません。この wikiで言及されているように、「Q」を何らかの識別子と組み合わせて使用​​して、仕様を拡張する人もいます。

2011 年のこのディスカッションで言及されているように、 Joda-Time 2は四半期をサポートしていません。

ISO 8601 は、正確に 52 または 53週の定義を定義しています。Joda-Time は、 weekOfWeekYear で表されるように、その概念をサポートしています。一部の企業では、1 から 52/53 の範囲のサブセットによって四半期を定義しています。

または、その年の 3 か月目、6 か月目、9 か月目、12 か月目の終わりまでに四半期を定義することもできます。Joda-Time には、月番号を指定できる DateTime クラスのコンストラクターがあります。メソッドwithTimeAtStartOfDay()を使用して Joda-Time に 1 日の最初の瞬間を取得させることに注意してください。これは、すべてのタイム ゾーンのすべての日に午前 0 時があるわけではないためです。

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 はうるう秒を無視しますが、私の主張は依然として有効です。

于 2013-11-12T08:05:43.047 に答える