oracle – JodaTime或Java 8是否特别支持JD Edwards日期和时间?
手头的主题是一个混乱的特定于域的问题,与Oracle的ERP软件JD Edwards中的日期一起使用.它的细节记录在
this question中.
在编写用于处理JD Edwards的日期和时间的包装类之前,我想知道JodaTime或Java 8是否为这种独特的时间格式引入了任何特殊支持,或者我是否必须进行重要的字符串操作,无论我使用哪些库. 这是一个模糊的问题,所以请仅在您具备此问题的特定知识和/或JodaTime / Java 8 / JSR 310时才做出响应. 加成: JCSBMDATE:115100,JCSBMTIME:120102.0 RLUPMJ:114317,RLUPMT:141805.0 此外,日期变量被转换为BigDecimal,时间是Double.所以,我可能会保留字符串解析器,但也可以编写本地采用BigDecimal / Double值的工厂方法. 似乎时间字段实际上是从一天开始的毫秒数(不是秒数),并且可以忽略“.0”.因此,必须执行转换和计算,如下所示: localDate.atTime(LocalTime.ofNanoOfDay(Long.parseLong(jdeTime)* 1000000)) JD Edwards日期定义实际上,根据a page at Oracle.com的简单描述,JD Edwards日期的细节并不是那么血腥:
条款: >我会把C部分称为“世纪偏移”,多少个世纪要加19个.使用0表示19xx年,1表示20xx年. java.time框架不包括直接支持解析或生成此格式的字符串,而不是我能找到的. JulianFields 有java.time.temporal.JulianFields,但这些是重新定义的版本Julian dates,我们计算一个时代的天数(1970-01-01(ISO)而不是历史悠久的11月24日,公元前4714年(预防格里高利) )),而完全忽略了几年.因此,这与JD Edwards定义无关,与问题中链接的该页面上的一些错误建议相反. 序数日期 此JD Edwards日期是ordinal date的版本.序数日期有时被称为“julian”日期随意(并且错误地)仅仅因为它共享计算一系列天数的想法.但是,序数日期表示从年初到年末的天数,总数在1到365/366(闰年)之间,不计算自某个时代以来成千上万的数字. 回到问题,在java.time中处理JD Edwards日期… 不,我没有找到任何直接或间接支持JD.time中内置的JD Edwards日期. java.date.format套餐似乎没有意识到约会的世纪,只有年份和时代.所以我无法找到定义JD Edwards日期的C部分. JD Edwards日期的最后一部分,即一年中的序数天数,在日期时间类和格式化类中都得到很好的处理. 包裹LocalDate 由于JD Edwards日期显然与java.time使用的ISO年表具有相同的逻辑,因此唯一真正的问题是根据此特定格式解析和生成String对象.可以从LocalDate中利用所有其他行为. 由于我找不到为此目的定义 理想情况下,我们将扩展 CAVEAT:使用风险自负.新鲜的代码,几乎没有运行,几乎没有测试.仅作为一个例子,不用于生产.根据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 () ); } } 跑步时
JD Edwards时间 至于JD Edwards时间格式,我搜索并找不到任何文档.如果您了解某些内容,请编辑您的问题以添加链接. JDE时代唯一提到的似乎是从午夜开始的秒数. 如果是这种情况(自午夜以来的计数), >从一天开始以来的整秒( 纳秒分辨率意味着小数部分的最多九位数.处理您提到的六位数没问题.只需数学,乘以/除以1_000L.请注意,这意味着可能的数据丢失,因为如果LocalTime值来自JD Edwards数据之外,您可能会截断分数的最后三位数(小数部分的第7,第8,第9位). [仅供参考,旧的java.util.Date/.Calendar类以及Joda-Time限制为毫秒级分辨率,小数部分的三位数. 不推荐:你可以做一些由LocalDate和LocalTime组成的组合类.或者使用LocalDateTime.关键问题是时区.如果JD Edwards日期时间始终在某个时区(如UTC),那么组合并使用OffsetDateTime可能是有意义的.但是如果它没有特定的时区上下文,如果这些值只是日期时间的模糊概念而不是时间轴上的特定点,那么请使用LocalDateTime,因为它没有时区.如果JDE始终为UTC,请将OffsetDateTime设置为ZoneOffset.UTC.如果要指定时区(偏移量加上处理异常的规则,例如DST),请使用ZonedDateTime. 推荐:分别使用LocalTime.我不认为你想在业务逻辑中使用我的JDEdwardsLocalDate类,特别是因为它不是适合java.time框架的完整实现.我的目的是在遇到JDE日期时使用该类立即转换为LocalDate. JDE时间也是如此,立即转换为 OffsetDateTime odt = OffsetDateTime.of( myLocalDate,myLocalTime,ZoneOffset.UTC ); 如果JDE日期&时间隐含了一些其他背景,然后分配预期的时区. ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.of( myLocalDate,zoneId ); 时区在这里至关重要.你必须理解一般的概念.请注意,LocalDate和LocalTime以及LocalDateTime不是时间轴上的一个时刻.在将它们调整为时区(或至少为offset-from-UTC)之前,它们没有特定含义. 如果不熟悉java.time类型,我在this Answer中包含的日期时间类型图可能会对您有所帮助. 你必须理解JDE日期和时间的含义.时间及其在您的应用/数据库中的使用.由于我无法找到关于JDE时间的任何信息,我无法了解JD Edwards对时区的意图.所以我不能提出更具体的建议. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |