JD エドワーズ日付定義
実際、Oracle.com のページにある次の簡単な説明によると、 JD Edwardsの日付の詳細はそれほど悲惨ではありません。
ユリウス日形式について
JD Edwards World ファイルの日付フィールドは、ユリウス形式で保存されます。…</p>
ユリウス (*JUL) 日付形式は CYYDDD です。
C を 19 に追加して世紀を作成します。つまり、0 + 19 = 19、1 + 19 = 20 です。YY は世紀内の年、DDD は年内の日です。
条項:
- 私はその部分を「世紀オフセット」と呼びます.
C
何世紀を追加するか19
. 0
何19xx
年も何年も1
使います20xx
。
- java.time フレームワークはこれ
DDD
を「DayOfYear」と呼びますが、「序日」は別の用語です。年内の日数に「ユリウス」を使用するのは一般的ですが、ユリウス日と矛盾して正しくありません。
java.time フレームワークには、この形式の文字列を解析または生成するための直接的なサポートが含まれていません。
JulianFields
ありますが、これらはユリウス日付java.time.temporal.JulianFields
の再定義されたバージョン用であり、エポック (歴史的な紀元前 4714 年 11 月 24 日 (先発グレゴリオ暦) ではなく 1970-01-01 (ISO)) からの日数を数えますが、年は無視します。完全に。したがって、これは JD Edwards の定義とは何の関係もありません。質問にリンクされているページの誤ったアドバイスとは対照的です。
序数日
この JD Edwards の日付は、序数の日付のバージョンです。序数の日付は、何気なく (そして誤って) 「ユリウス」日付と呼ばれることがあります。これは、一連の日数を数えるという考え方を共有しているからです。しかし、序数の日付は、年の初めから年末までの日数を常に 1 ~ 365/366 (閏年) の間でカウントし、あるエポック以降はカウントせず、数千の数に成長します。
質問に戻り、java.time で JD Edwards の日付を処理します…</p>
いいえ、JD Edwards の日付が java.time に組み込まれていることを直接的または間接的にサポートしているとは思いません。
java.date.formatパッケージは、日付の世紀を認識しておらず、年と時代だけを認識しているようです。C
したがって、JD Edwards の日付の一部を定義する方法はありません。
JD Edwards の日付の最後の部分 (1 年の序数) は、日時クラスとフォーマット クラスの両方で適切に処理されます。
包むLocalDate
JD Edwards の日付は明らかに java.time で使用される ISO 暦と同じロジックを持っているため、当面の唯一の実際の問題は、この特定の形式に従って String オブジェクトを解析および生成することです。他のすべての動作は、LocalDate
.
java.time.format.DateTimeFormatter
この目的でを定義する方法が見つからないので、これらの雑用を処理するユーティリティ クラスを作成することをお勧めします。
理想的には、クラスを拡張して、そのメソッドとメソッドLocalDate
をオーバーライドします。そしておそらく方法。ただし、クラスはマークされており、拡張できません。したがって、以下に示すこのクラスのようなものを作成し、.parse
toString
getCenturyOffset
LocalDate
final
LocalDate
警告:自己責任で使用してください。新しいコード、ほとんど実行されず、ほとんどテストされていません。例としてのものであり、本番環境での使用を意図したものではありません。ISC ライセンスの条項に従って使用してください。
package com.example.whatever;
import java.time.LocalDate;
import java.time.ZoneId;
/**
* Wraps a 'LocalDate' to provide parsing/generating of strings in format known
* as JD Edwards date.
*
* Format is CYYDDD where C is the number of centuries from 1900, YY is the year
* within that century, and DDD is the ordinal day within the year (1-365 or
* 1-366 in Leap Year).
*
* Immutable object. Thread-safe (hopefully! No guarantees).
*
* I would rather have done this by extending the 'java.time.LocalDate' class, but that class is marked 'final'.
*
* Examples: '000001' is January 1 of 1900. '116032' is February 1, 2016.
*
* © 2016 Basil Bourque. This source code may be used according to terms of the ISC License at https://opensource.org/licenses/ISC
*
* @author Basil Bourque
*/
public class JDEdwardsLocalDate {
private LocalDate localDate = null;
private int centuryOffset;
private int yearOfCentury;
private String formatted = null;
// Static Factory method, in lieu of public constructor.
static public JDEdwardsLocalDate from ( LocalDate localDateArg ) {
return new JDEdwardsLocalDate ( localDateArg );
}
// Static Factory method, in lieu of public constructor.
static public JDEdwardsLocalDate parse ( CharSequence charSequenceArg ) {
if ( null == charSequenceArg ) {
throw new IllegalArgumentException ( "Passed CharSequence that is null. Message # 0072f897-b05f-4a0e-88d9-57cfd63a712c." );
}
if ( charSequenceArg.length () != 6 ) {
throw new IllegalArgumentException ( "Passed CharSequence that is not six characters in length. Message # eee1e134-8ec9-4c92-aff3-9296eac1a84a." );
}
String string = charSequenceArg.toString ();
// Should have all digits. Test by converting to an int.
try {
int testAsInteger = Integer.parseInt ( string );
} catch ( NumberFormatException e ) {
throw new IllegalArgumentException ( "Passed CharSequence contains non-digits. Fails to convert to an integer value. Message # 0461f0ee-b6d6-451c-8304-6ceface05332." );
}
// Validity test passed.
// Parse.
int centuryOffset = Integer.parseInt ( string.substring ( 0 , 1 ) ); // Plus/Minus from '19' (as in '1900').
int yearOfCentury = Integer.parseInt ( string.substring ( 1 , 3 ) );
int ordinalDayOfYear = Integer.parseInt ( string.substring ( 3 ) );
int centuryStart = ( ( centuryOffset + 19 ) * 100 ); // 0 -> 1900. 1 -> 2000. 2 -> 2100.
int year = ( centuryStart + yearOfCentury );
LocalDate localDate = LocalDate.ofYearDay ( year , ordinalDayOfYear );
return new JDEdwardsLocalDate ( localDate );
}
// Constructor.
private JDEdwardsLocalDate ( LocalDate localDateArg ) {
this.localDate = localDateArg;
// Calculate century offset, how many centuries plus/minus from 1900.
int year = this.localDate.getYear ();
int century = ( year / 100 );
this.yearOfCentury = ( year - ( century * 100 ) ); // example: if 2016, return 16.
this.centuryOffset = ( century - 19 );
// Format as string.
String paddedYearOfCentury = String.format ( "%02d" , this.yearOfCentury );
String paddedDayOfYear = String.format ( "%03d" , this.localDate.getDayOfYear () );
this.formatted = ( this.centuryOffset + paddedYearOfCentury + paddedDayOfYear );
}
@Override
public String toString () {
return this.formatted;
}
public LocalDate toLocalDate () {
// Returns a java.time.LocalDate which shares the same ISO chronology as a JD Edwards Date.
return this.localDate;
}
public int getDayOfYear () {
// Returns ordinal day number within the year, 1-365 inclusive or 1-366 for Leap Year.
return this.localDate.getDayOfYear();
}
public int getYear () {
// Returns a year number such as 2016.
return this.localDate.getYear();
}
public int getYearOfCentury () {
// Returns a number within 0 and 99 inclusive.
return this.yearOfCentury;
}
public int getCenturyOffset () {
// Returns 0 for 19xx dates, 1 for 20xx dates, 2 for 21xx dates, and so on.
return this.centuryOffset;
}
public static void main ( String[] args ) {
// '000001' is January 1, 1900.
JDEdwardsLocalDate jde1 = JDEdwardsLocalDate.parse ( "000001" );
System.out.println ( "'000001' = JDEdwardsLocalDate: " + jde1 + " = LocalDate: " + jde1.toLocalDate () + " Should be: January 1, 1900. " );
// '116032' is February 1, 2016.
JDEdwardsLocalDate jde2 = JDEdwardsLocalDate.parse ( "116032" );
System.out.println ( "'116032' = JDEdwardsLocalDate: " + jde2 + " = LocalDate: " + jde2.toLocalDate () + " Should be: February 1, 2016." );
// Today
LocalDate today = LocalDate.now ( ZoneId.systemDefault () );
JDEdwardsLocalDate jdeToday = JDEdwardsLocalDate.from ( today );
System.out.println ( "LocalDate.now(): " + today + " = JDEdwardsLocalDate: " + jdeToday + " to LocalDate: " + jdeToday.toLocalDate () );
}
}
走るとき。
'000001' = JDEdwardsLocalDate: 000001 = LocalDate: 1900-01-01 1900 年 1 月 1 日である必要があります。
'116032' = JDEdwardsLocalDate: 116032 = LocalDate: 2016-02-01 2016 年 2 月 1 日である必要があります。
LocalDate.now(): 2016-05-09 = JDEdwardsLocalDate: 116130 から LocalDate: 2016-05-09
JD Edwards 時刻
JD Edwards の時刻形式については、検索してもドキュメントが見つかりませんでした。いくつか知っている場合は、質問を編集してリンクを追加してください。JDE 時間についての唯一の言及は、真夜中からの秒数のようでした。
その場合 (午前 0 時からのカウント)、java.time.LocalTime
クラスで対応できます。ALocalTime
はインスタンス化して、次のいずれかとして読み取ることができます。
ナノ秒の分解能とは、小数部の最大9桁を意味します。あなたが言及した6桁の処理に問題はありません。ただ計算をして、 を掛けたり割ったりして1_000L
ください。LocalTime
値が JD Edwards データの外部から取得された場合、小数部の最後の 3 桁 (小数部の 7 桁目、8 桁目、9 桁目) が切り捨てられる可能性があるため、データが失われる可能性があることに注意してください。[参考までに、古い java.util.Date/.Calendar クラスと Joda-Time は、小数点以下 3 桁のミリ秒単位の解像度に制限されています。]
非推奨:とで構成されたある種のコンボ クラスを実行できます。またはを使用します。重要な問題はタイムゾーンです。JD Edwards の日時が常に UTC などの特定のタイム ゾーンにある場合は、. ただし、特定のタイム ゾーン コンテキストがない場合、値がタイムライン上の特定のポイントではなく日付/時間のあいまいなアイデアである場合は、タイム ゾーンがないので使用します。JDE が常に UTC である場合は、set to を使用します。タイム ゾーン (オフセットとDSTなどの異常を処理するためのルール) を指定する場合は、 を使用します。LocalDate
LocalTime
LocalDateTime
OffsetDateTime
LocalDateTime
OffsetDateTime
ZoneOffset.UTC
ZonedDateTime
推奨: LocalTime を個別に使用します。ビジネス ロジックで私の JDEdwardsLocalDate クラスを使用したいとは思わないでしょう。これは特に、java.time フレームワークに適合する完全な実装ではないためです。私の意図は、そのクラスを使用してLocalDate
、JDE 日付に遭遇したときにすぐに変換することです。同じことが JDE 時刻にも当てはまり、LocalTime
すぐに変換します。コンテキストが常に UTC の場合は、UTC を使用して を作成し、OffsetDateTime
それをビジネス ロジックに渡します。必要な場合にのみ、JDE の日付と時刻に戻ります (その JDE タイプのデータベース列に永続化するか、その JDE プレゼンテーションを期待しているユーザーに報告します)。
OffsetDateTime odt = OffsetDateTime.of( myLocalDate , myLocalTime , ZoneOffset.UTC );
JDE の日付と時刻に他のコンテキストが含まれている場合は、目的のタイム ゾーンを割り当てます。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.of( myLocalDate , myLocalTime , zoneId );
ここではタイムゾーンが重要です。一般的な概念を理解する必要があります。LocalDate
と と はタイムライン上の瞬間ではないことをLocalTime
明確にLocalDateTime
してください。タイムゾーン(または少なくともUTC からのオフセット)に調整するまで、特定の意味はありません。
この回答に含まれる日時型の図は、java.time 型に慣れていない場合に役立ちます。
また、JDE の日付と時刻の意味と、アプリやデータベースでの使用方法を理解する必要があります。JDE 時間については何も見つけることができなかったので、タイム ゾーンに対する JD Edwards の意図については何も知ることができませんでした。したがって、これ以上具体的に提案することはできません。