JodaTime 或 Java 8 是否有特殊支持 JD Edwards 日期和时间?
Does JodaTime or Java 8 have special support JD Edwards Date and Time?
手头的主题是在 Oracle 的 ERP 软件 JD Edwards 中处理日期的混乱的特定于域的问题。其详细信息记录在 this question.
中
在编写用于处理来自 JD Edwards 的日期和时间的包装器 类 之前,我想知道 JodaTime 或 Java 8 是否引入了对这种独特时间格式的任何特殊支持,或者我是否'不管我使用什么库,我都必须进行大量的字符串操作。
这是一个晦涩难懂的问题,因此请仅在您对此问题有具体了解的情况下做出回应,and/or JodaTime/Java 8/JSR 310。
补充:
根据 Basil Bourque 的要求,添加伴随上述日期的时间戳示例。以下是来自不同表的 date/time 字段的两个示例:
JCSBMDATE:115100, JCSBMTIME:120102.0
RLUPMJ:114317, RLUPMT:141805.0
此外,日期变量被转换为 BigDecimal,时间是 Double。所以,我可能会保留字符串解析器,但也会编写原生采用 BigDecimal/Double 值的工厂方法。
看来时间字段实际上是从一天开始算起的毫秒数(不是秒数),“.0”可以忽略。因此,必须像这样执行转换和计算:
localDate.atTime(LocalTime.ofNanoOfDay(Long.parseLong(jdeTime) * 1000000))
否:Joda Time 和 Java8 都不支持 JD Edwards 时间表示。
JD Edwards 日期定义
其实详细一个JD Edwards date is not so gory, according to this simple description on a page at Oracle.com:
About the Julian Date Format
Date fields in JD Edwards World files are stored in the Julian format. …
The Julian (*JUL) date format is CYYDDD, where:
C is added to 19 to create the century, i.e. 0 + 19 = 19, 1 + 19 = 20. YY is the year within the century, DDD is the day in the year.
条款:
- 我将
C
部分称为“世纪偏移量”,即要添加到 19
的世纪数。 19xx
年使用 0
,20xx
年使用 1
。
- java.time 框架将
DDD
称为“DayOfYear”,“序号日期”是另一个术语。使用“Julian”表示一年内的天数很常见但不正确,与 Julian Day. 相冲突
java.time 框架不包括对解析或生成这种格式的字符串的直接支持,我找不到。
JulianFields
有 java.time.temporal.JulianFields
,但这些是 Julian dates 的重新定义版本,我们从纪元(1970-01-01 (ISO) 而不是历史性的 11 月开始计算天数24, 4714 BC (proleptic Gregorian)),同时完全忽略年份。所以这与 JD Edwards 的定义无关,与问题中链接的该页面上的一些不正确建议相反。
序号日期
这个 JD Edwards 日期是 ordinal date 的一个版本。序数日期有时被随意(并且错误地)称为“julian”日期,只是因为它共享计算一系列天数的想法。但是一个序数日期计算从年初到年底的天数,这个数字总是在 1 到 365/366(闰年)之间,从某个纪元开始计算,并增长到数千。
回到问题,处理 java.time 中的 JD Edwards 日期…
不,我没有发现 java.time 内置的 JD Edwards 日期有任何直接或间接的支持。
java.date.format 包似乎不知道日期的世纪,只知道年份和纪元。所以我找不到定义 JD Edwards 日期的 C
部分的方法。
JD Edwards 日期的最后一部分,即一年中的序号天数,在日期时间 classes 和格式 classes 中都得到了很好的处理。
换行LocalDate
由于 JD Edwards 日期显然与 java.time 使用的 ISO 年表具有相同的逻辑,手头唯一真正的问题是根据这种特定格式解析和生成 String 对象。 LocalDate
.
可以利用所有其他行为
由于我找不到为此目的定义 java.time.format.DateTimeFormatter
的方法,我建议编写一个实用程序 class 来处理这些琐事。
理想情况下,我们会扩展 LocalDate
class, overriding its parse
and toString
方法。也许还有一个 getCenturyOffset
方法。但是 LocalDate
class 被标记为 final
并且无法扩展。所以我会创建如下所示的 class ,包装 LocalDate
.
警告: 使用风险自负。新鲜代码,勉强 运行,几乎没有测试。仅作为示例,不适用于生产。按照ISC License.
的条款使用
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 Should be: January 1, 1900.
'116032' = JDEdwardsLocalDate: 116032 = LocalDate: 2016-02-01 Should be: February 1, 2016.
LocalDate.now(): 2016-05-09 = JDEdwardsLocalDate: 116130 to LocalDate: 2016-05-09
JD Edwards 时间
至于 JD Edwards 时间格式,我搜索过但找不到任何文档。如果您知道一些,请编辑您的问题以添加链接。唯一提到的 JDE 时间似乎是从午夜算起的秒数。
如果是这种情况(自午夜以来的计数),java.time.LocalTime
class 已涵盖。 LocalTime
可以实例化并读取为:
- 自一天开始以来的整秒数 (
withSecond
, ofSecondOfDay
)
- 自一天开始以来的小数秒,分辨率为纳秒 (
withNano
, ofNanoOfDay
)
纳秒分辨率意味着最多 9 位小数。处理您提到的六位数字没问题。只需计算 multiply/divide 乘以 1_000L
。请注意,这意味着可能会丢失数据,因为如果 LocalTime
值来自 JD Edwards 外部,您可能会 t运行 计算小数的最后三位数字(小数的第 7、8、9 位)数据。 [仅供参考,旧的 java.util.Date/.Calendar classes 以及 Joda-Time 仅限于毫秒分辨率,对于三位小数。]
不推荐:你可以做一些组合class,由一个LocalDate
和一个LocalTime
组成。或者使用 LocalDateTime
。关键问题是时区。如果 JD Edwards 日期时间始终处于某个时区(例如 UTC),那么组合和使用 OffsetDateTime
可能是有意义的。但是如果它没有特定的时区上下文,如果值只是日期时间的模糊概念而不是时间轴上的特定点,那么使用 LocalDateTime
因为它没有时区。如果 JDE 始终采用 UTC,请将 OffsetDateTime
设置为 ZoneOffset.UTC
。如果要指定时区(偏移加上处理异常的规则如DST),使用ZonedDateTime
.
建议:单独使用 LocalTime。我认为您不想在业务逻辑中使用我的 JDEdwardsLocalDate class,尤其是因为它不是适合 java.time 框架的完整实现。 我的意图是在遇到 JDE 日期时使用 class 立即将 转换为 LocalDate
。 JDE 时间也是如此,使用 UTC 转换为 LocalTime
immediately. If their context is always UTC, create an 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
是 而不是 时间轴上的一个时刻。 它们没有特定含义,直到您将它们调整到一个时区(或至少一个 offset-from-UTC)。
如果您不熟悉 java.time 类型,我在 中包含的日期时间类型图表可能会对您有所帮助。
并且您必须了解 JDE 日期和时间的含义及其在 apps/databases 中的使用。由于找不到有关 JDE 时间的任何信息,因此我无法了解 JD Edwards 对时区的意图。所以我无法提出更具体的建议。
手头的主题是在 Oracle 的 ERP 软件 JD Edwards 中处理日期的混乱的特定于域的问题。其详细信息记录在 this question.
中在编写用于处理来自 JD Edwards 的日期和时间的包装器 类 之前,我想知道 JodaTime 或 Java 8 是否引入了对这种独特时间格式的任何特殊支持,或者我是否'不管我使用什么库,我都必须进行大量的字符串操作。
这是一个晦涩难懂的问题,因此请仅在您对此问题有具体了解的情况下做出回应,and/or JodaTime/Java 8/JSR 310。
补充: 根据 Basil Bourque 的要求,添加伴随上述日期的时间戳示例。以下是来自不同表的 date/time 字段的两个示例:
JCSBMDATE:115100, JCSBMTIME:120102.0
RLUPMJ:114317, RLUPMT:141805.0
此外,日期变量被转换为 BigDecimal,时间是 Double。所以,我可能会保留字符串解析器,但也会编写原生采用 BigDecimal/Double 值的工厂方法。
看来时间字段实际上是从一天开始算起的毫秒数(不是秒数),“.0”可以忽略。因此,必须像这样执行转换和计算:
localDate.atTime(LocalTime.ofNanoOfDay(Long.parseLong(jdeTime) * 1000000))
否:Joda Time 和 Java8 都不支持 JD Edwards 时间表示。
JD Edwards 日期定义
其实详细一个JD Edwards date is not so gory, according to this simple description on a page at Oracle.com:
About the Julian Date Format
Date fields in JD Edwards World files are stored in the Julian format. …
The Julian (*JUL) date format is CYYDDD, where:
C is added to 19 to create the century, i.e. 0 + 19 = 19, 1 + 19 = 20. YY is the year within the century, DDD is the day in the year.
条款:
- 我将
C
部分称为“世纪偏移量”,即要添加到19
的世纪数。19xx
年使用0
,20xx
年使用1
。 - java.time 框架将
DDD
称为“DayOfYear”,“序号日期”是另一个术语。使用“Julian”表示一年内的天数很常见但不正确,与 Julian Day. 相冲突
java.time 框架不包括对解析或生成这种格式的字符串的直接支持,我找不到。
JulianFields
有 java.time.temporal.JulianFields
,但这些是 Julian dates 的重新定义版本,我们从纪元(1970-01-01 (ISO) 而不是历史性的 11 月开始计算天数24, 4714 BC (proleptic Gregorian)),同时完全忽略年份。所以这与 JD Edwards 的定义无关,与问题中链接的该页面上的一些不正确建议相反。
序号日期
这个 JD Edwards 日期是 ordinal date 的一个版本。序数日期有时被随意(并且错误地)称为“julian”日期,只是因为它共享计算一系列天数的想法。但是一个序数日期计算从年初到年底的天数,这个数字总是在 1 到 365/366(闰年)之间,从某个纪元开始计算,并增长到数千。
回到问题,处理 java.time 中的 JD Edwards 日期…
不,我没有发现 java.time 内置的 JD Edwards 日期有任何直接或间接的支持。
java.date.format 包似乎不知道日期的世纪,只知道年份和纪元。所以我找不到定义 JD Edwards 日期的 C
部分的方法。
JD Edwards 日期的最后一部分,即一年中的序号天数,在日期时间 classes 和格式 classes 中都得到了很好的处理。
换行LocalDate
由于 JD Edwards 日期显然与 java.time 使用的 ISO 年表具有相同的逻辑,手头唯一真正的问题是根据这种特定格式解析和生成 String 对象。 LocalDate
.
由于我找不到为此目的定义 java.time.format.DateTimeFormatter
的方法,我建议编写一个实用程序 class 来处理这些琐事。
理想情况下,我们会扩展 LocalDate
class, overriding its parse
and toString
方法。也许还有一个 getCenturyOffset
方法。但是 LocalDate
class 被标记为 final
并且无法扩展。所以我会创建如下所示的 class ,包装 LocalDate
.
警告: 使用风险自负。新鲜代码,勉强 运行,几乎没有测试。仅作为示例,不适用于生产。按照ISC License.
的条款使用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 Should be: January 1, 1900.
'116032' = JDEdwardsLocalDate: 116032 = LocalDate: 2016-02-01 Should be: February 1, 2016.
LocalDate.now(): 2016-05-09 = JDEdwardsLocalDate: 116130 to LocalDate: 2016-05-09
JD Edwards 时间
至于 JD Edwards 时间格式,我搜索过但找不到任何文档。如果您知道一些,请编辑您的问题以添加链接。唯一提到的 JDE 时间似乎是从午夜算起的秒数。
如果是这种情况(自午夜以来的计数),java.time.LocalTime
class 已涵盖。 LocalTime
可以实例化并读取为:
- 自一天开始以来的整秒数 (
withSecond
,ofSecondOfDay
) - 自一天开始以来的小数秒,分辨率为纳秒 (
withNano
,ofNanoOfDay
)
纳秒分辨率意味着最多 9 位小数。处理您提到的六位数字没问题。只需计算 multiply/divide 乘以 1_000L
。请注意,这意味着可能会丢失数据,因为如果 LocalTime
值来自 JD Edwards 外部,您可能会 t运行 计算小数的最后三位数字(小数的第 7、8、9 位)数据。 [仅供参考,旧的 java.util.Date/.Calendar classes 以及 Joda-Time 仅限于毫秒分辨率,对于三位小数。]
不推荐:你可以做一些组合class,由一个LocalDate
和一个LocalTime
组成。或者使用 LocalDateTime
。关键问题是时区。如果 JD Edwards 日期时间始终处于某个时区(例如 UTC),那么组合和使用 OffsetDateTime
可能是有意义的。但是如果它没有特定的时区上下文,如果值只是日期时间的模糊概念而不是时间轴上的特定点,那么使用 LocalDateTime
因为它没有时区。如果 JDE 始终采用 UTC,请将 OffsetDateTime
设置为 ZoneOffset.UTC
。如果要指定时区(偏移加上处理异常的规则如DST),使用ZonedDateTime
.
建议:单独使用 LocalTime。我认为您不想在业务逻辑中使用我的 JDEdwardsLocalDate class,尤其是因为它不是适合 java.time 框架的完整实现。 我的意图是在遇到 JDE 日期时使用 class 立即将 转换为 LocalDate
。 JDE 时间也是如此,使用 UTC 转换为 LocalTime
immediately. If their context is always UTC, create an 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
是 而不是 时间轴上的一个时刻。 它们没有特定含义,直到您将它们调整到一个时区(或至少一个 offset-from-UTC)。
如果您不熟悉 java.time 类型,我在
并且您必须了解 JDE 日期和时间的含义及其在 apps/databases 中的使用。由于找不到有关 JDE 时间的任何信息,因此我无法了解 JD Edwards 对时区的意图。所以我无法提出更具体的建议。