我有一个数据库,用于存储日期和日期时间(分别为INTEGER和DOUBLE)作为已修改的儒略日数(MJD)。修改后的儒略日数是自1858年11月17日午夜UTC以来连续的天数。根据定义,它们始终以UTC计算,与格林尼治标准时间+0:00偏移,并且不针对夏令时进行调整。这些属性使用DateTimes简化了某些操作,例如优先级和日期算术。

不利之处在于,在使用前后,MJD必须从UTC重新定位并重新定位回UTC,特别是对于日间边界至关重要的应用程序(例如,Medicare将可计费的日期边界识别为-local-time中的午夜)。

请考虑以下静态工厂方法,其目的是将"区域日号"(基本上是已添加了适当偏移量的MJD,使其代表本地DateTime)迁移到MJD(在UTC中)。

public static MJD ofDayNumberInZone(double regDN, ZoneId zone) {

:

:

}

从直观上看,很明显,如果您具有本地日期和时间,并且知道本地时区,则应该具有将regDN偏移回UTC所需的所有信息(MJD要求)。

实际上,使用以前的Java Calendar API编写此函数相当简单。 regDN易于转换为Date,用于设置GregorianCalendar实例。知道"本地时区"后,日历会报告ZONE_OFFSET和DST_OFFSET值,这些值随后可用于将天数调整为MJD。

这是我尝试在Java 8 DateTime API中编写类似的算法的尝试:

public static MJD ofDayNumberInZone(double zonedMJD, ZoneId zone) {

double epochSec = ((zonedMJD - MJD.POSIX_EPOCH_AS_MJD) * 86400.0);

LocalDateTime dt = LocalDateTime

.ofEpochSecond(

(long) epochSec,

(int) (epochSec - Math.floor(epochSec) * 1000000000.0),

--->                zone.getRules().getOffset( )

);

}

该问题如箭头所示。使用ofEpochSecond方法构造LocalDateTime实例似乎要求您事先知道偏移量,这似乎违反直觉(我已经有了当地时间和时区,这就是我想要的偏移量)。

我没有成功找到使用Java 8 API从本地时间返回UTC的偏移量的简单方法。虽然我可以继续使用旧的Calendar API,但是新的DateTime库具有引人注目的优点...因此,我想尝试一下。我想念什么?

编辑:这是一个使用旧的Java Calendar API的示例,该示例如何将任意时区中的天数和小数天数"分解"为UTC。此方法采用一个双精度数字,即"区域化日期数"和一个时区对象。它使用GregorianCalendar将参数转换为从纪元到毫秒的UTC计数:

private static final Object             lockCal = new Object();

private static final SimpleDateFormat       SDF = new SimpleDateFormat();

private static final GregorianCalendar      CAL = new

GregorianCalendar(TimeZone.getTimeZone(HECTOR_ZONE));

:

:

public static MJD ofDayNumberInZone(double rdn, TimeZone tz) {

Date dat = new Date((long) ((rdn - MJD.POSIX_EPOCH_AS_MJD) *

(86400.0 * 1000.0)));

return MJD.ofDateInZone(dat, tz);

}

public static MJD ofDateInZone(Date dat, TimeZone tz) {

long utcMillisFromEpoch;

synchronized(lockCal) {

CAL.setTimeZone(tz);

CAL.setTime(dat);

utcMillisFromEpoch = CAL.getTimeInMillis();

}

return MJD.ofEpochMillisInUTC(utcMillisFromEpoch);

}

public static MJD ofEpochMillisInUTC(long millis)

{ return new MJD((millis / (86400.0 * 1000.0)) + POSIX_EPOCH_AS_MJD);          }

那么该方法的目的是将Zoned MJD转换为UTC MJD吗?

我不使用Java,但可以想象您成功了。我希望您能够在程序运行时获得补偿,或者考虑到日期并更改当年夏令时的补偿。我不希望Java在DST的开始/结束日期不同时能够提供历史偏移,当然,预测未来国会的行动是不可能的。那么,您是否为历史或将来的日期/时间预留了适当的配额?

@GerardAshton:这是与我的问题无关的单独问题,但是Java DateTime API完全支持IANA时区数据库,并为特定于区域的时间偏移量计算提供了历史上准确的偏移量。

我注意到getOffset方法需要一个瞬间,该瞬间是从历元和纳秒以来的几秒钟创建的。但是,如果您不知道偏移量并且不知道格林威治/ UTC时间,那么您将无法计算出自该纪元以来的秒数,因此无法创建时刻。

@GerardAshton:这是我遇到的悖论……如果-您-了解当地时间和当地时区,那么-您-有足够的信息可以正确到达UTC。但是,Java 8 DateTime API似乎无法构造任何Instant,除非它知道如何在UTC内部进行表示(显然,以先于UTC的偏移量为前提)。我被困在如何获取当地时间和时区并从中获取即时信息。在旧的API中这很简单,但是我发现新API难以使用。

@fdsa:是的,这是问题的简要说明:采取分区MJD(如果您可以同意有这样的事情;所有MJD都应该位于UTC中),然后从中到达UTC MJD。

我查看了Java 8日期文档。看来有两种非UTC /格林威治时间。 Java.time包未将LocalDateTime连接到任何特定时区,因此需要从上下文或与Java.time不相关的源代码中找出它。 ZonedDateTime是Java.time跟踪区域的本地时间。 Java知道规则是什么。如果您探索ZonedDateTime,则可能会找到所需的内容。在某些情况下,无法进行转换;本地-> UTC在秋季DST中更改。

根据您的评论,您的核心问题似乎是将不带时区的日期时间(a LocalDateTime)转换为带区矩(a ZonedDateTime)的歧义。您解释说诸如夏令时(DST)之类的异常可能导致无效值。

ZonedDateTime zdt = myLocalDateTime.atZone( myZoneId );

这是真的。在DST中"春季前移"或"后退"切换时,没有完美的解决方案。但是,java.time类确实通过采用某种策略来解决歧义。您可能同意也可能不同意该政策。但是,如果您同意,则可以依靠java.time来确定结果。

引用ZonedDateTime.ofLocal的文档:

In the case of an overlap, where clocks are set back, there are two valid offsets. If the preferred offset is one of the valid offsets then it is used. Otherwise the earlier valid offset is used, typically corresponding to"summer".

In the case of a gap, where clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to"summer".

LocalDate modifiedJulianEpoch = LocalDate.of( 1858 , 11 , 17 );

LocalDate today = LocalDate.now( ZoneOffset.UTC );

long days = ChronoUnit.DAYS.between (  modifiedJulianEpoch , today );

today: 2017-03-19

days: 57831

我不太了解您的问题。但是在我看来,MJD(修改后的朱利安天数)的目的是要有一种方法来跟踪"一个真实时间",以避免所有时区的混乱。在标准ISO 8601日历系统中,UTC扮演着"一次真实时间"的角色。因此,我建议您坚持使用UTC。

当您需要考虑某个地区的时钟时间(例如您在该地区结束时间的Medicare示例)时,请确定该地区的时钟时间,然后转换为UTC。根据定义,java.time中的Instant类始终使用UTC。

ZoneId z = ZoneId.of("America/Los_Angeles" );

LocalDate localDate = LocalDate.now( z );

ZonedDateTime firstMomentNextDay = localDate.plusDays( 1 ).atStartOfDay( z );

Instant medicareExpiration = firstMomentNextDay.toInstant(); // UTC

BigDecimal modJulDays = this.convertInstantToModifiedJulianDays( medicareExpiration ) ;

在精度很重要的地方使用小数位小数时,请使用BigDecimal。使用double,double,float或float意味着使用浮点技术,该技术会牺牲精度以提高性能。

这是一些代码的粗略用法,可以完成从BigDecimal(Modified Julian Days)到Instant的转换。我想有些聪明的人可能会找到此代码的精简版本,但我的代码似乎在起作用。使用风险自负。我几乎没有测试过此代码。

public Instant convertModifiedJulianDaysToInstant ( BigDecimal modJulDays ) {

Instant epoch = OffsetDateTime.of ( 1858, 11, 17, 0, 0, 0, 0, ZoneOffset.UTC ).toInstant ( ); // TODO: Make into a constant to optimize.

long days = modJulDays.toBigInteger ( ).longValue ( );

BigDecimal fractionOfADay = modJulDays.subtract ( new BigDecimal ( days ) ); // Extract the fractional number, separate from the integer number.

BigDecimal secondsFractional = new BigDecimal ( TimeUnit.DAYS.toSeconds ( 1 ) ).multiply ( fractionOfADay );

long secondsWhole = secondsFractional.longValue ( );

long nanos = secondsFractional.subtract ( new BigDecimal ( secondsWhole ) ).multiply ( new BigDecimal ( 1_000_000_000L ) ).longValue ( );

Duration duration = Duration.ofDays ( days ).plusSeconds ( secondsWhole ).plusNanos ( nanos );

Instant instant = epoch.plus ( duration );

return instant;

}

并朝另一个方向发展。

public BigDecimal convertInstantToModifiedJulianDays ( Instant instant ) {

Instant epoch = OffsetDateTime.of ( 1858, 11, 17, 0, 0, 0, 0, ZoneOffset.UTC ).toInstant ( ); // TODO: Make into a constant to optimize.

Duration duration = Duration.between ( epoch, instant );

long wholeDays = duration.toDays ( );

Duration durationRemainder = duration.minusDays ( wholeDays );

BigDecimal wholeDaysBd = new BigDecimal ( wholeDays );

BigDecimal partialDayInNanosBd = new BigDecimal ( durationRemainder.toNanos ( ) ); // Convert entire duration to a total number of nanoseconds.

BigDecimal nanosInADayBd = new BigDecimal ( TimeUnit.DAYS.toNanos ( 1 ) );  // How long is a standard day in nanoseconds?

int scale = 9; // Maximum number of digits to the right of the decimal point.

BigDecimal partialDayBd = partialDayInNanosBd.divide ( nanosInADayBd ); // Get a fraction by dividing a total number of nanos in a day by our partial day of nanos.

BigDecimal result = wholeDaysBd.add ( partialDayBd );

return result;

}

调用那些转换方法。

BigDecimal input = new BigDecimal ("57831.5" );

Instant instant = this.convertModifiedJulianDaysToInstant ( input );

BigDecimal output = this.convertInstantToModifiedJulianDays ( instant );

转储到控制台。

System.out.println ("input.toString():" + input );

System.out.println ("instant.toString():" + instant );

System.out.println ("output.toString():" + output );

input.toString(): 57831.5

instant.toString(): 2017-03-19T12:00:00Z

output.toString(): 57831.5

查看在IdeOne.com上实时运行的所有代码。

另外,我对类似问题的回答可能会有所帮助。

java moment 日期转换_关于日期:如何使用Java 8 DateTime API转换修改后的儒略日数字...相关推荐

  1. access查询出生日期格式转换_设置日期和时间字段的格式

    日期和时间格式概述 Access 会自动以 "常规日期" 和 "长时间" 格式显示日期和时间. 日期显示为美国的 "mm/dd/yyyy", ...

  2. java web 图书管理系统_图书管理系统,源代码 Java初级小项目

    今天再给大家分享一个小项目:MiNi图书管理系统.用的是Java语言开发的,代码不多,大概260行左右吧,系统是实现图书的新增图书.删除图书.借阅图书.归还图书.查看图书等简单的功能(后附源代码)! ...

  3. java医院挂号代码_基于SSM开发的Java医院预约挂号系统 源码下载

    这是一个基于SSM开发的Java医院预约挂号系统,源码中附带主工程以及数据库文件. 目前已知Bug:因为时间预约信息是假数据,控制预约日历显示的代码在data/index.js,因为js写的有点bug ...

  4. java护照号码校验_学无止境之小白学java……第001天

    学习主题:预科阶段 对应视频: http://www.itbaizhan.cn/course/id/18.html 对应作业: 1. 为什么需要学编程,什么样的人可以做程序员? 编程是现实逻辑的表达, ...

  5. java青蛙过河打字_趣味算法——青蛙过河(JAVA)

    青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间有若干个石块间隔,有两队青蛙在过河,每队有3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙向前移动.在移动过程中,青蛙可以向 ...

  6. java 工具类命名_排名前16的Java工具类

    在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选取的5万个开源项目源码. 一. ...

  7. java rhino js类_让Rhino JS看Java类

    我正在玩 Rhino,我已经成功使用了stdlib中的Java类,但没有使用我编译的Java代码. 例如,这工作正常: print(new java.util.Date()); 但是使用NanoHTT ...

  8. java实现上传_文件上传(java)

    最近看了一本书上的代码,代码的主要功能是实现文件的上传.但是,当我运行代码的时候竟然报错了.(我用的IDEA).有错就解决吧.以下是我遇到的几个错误. 废话不多说先附上源代码. UploadServl ...

  9. java azure blob 查询_快速入门:适用于 Java 的 Azure Blob 存储客户端库 v8 | Microsoft Docs...

    您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn. 快速入门:使用 Jav ...

最新文章

  1. 融合AI与大数据技术,腾讯教育发布智能作业灯
  2. python下载教程pdf-Python教程PDF合集下载
  3. ASP.NET中 DropDownList+GridView(网格视图)的使用前台绑定[高]
  4. 准备入门IC的全局观念系列-下
  5. Tableau必知必会之妙用Fixed函数聚合分析维度
  6. 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框
  7. Wannafly挑战赛17 - 走格子(模拟)
  8. 结合html和css制作页面的布局结构,CSS Div网页布局中的结构与表现
  9. 嵌套饼图_旭日图的效率,高到饼图都羡慕
  10. PHP+MySql+PDO小案例—文章管理系统
  11. idea 自动加头部注释
  12. Matlab图像处理函数:regionprops
  13. HTML网页作业个人网站源码div+css布局
  14. excel取消分页符
  15. 一起实践神经网络INT8量化系列教程(一)
  16. 【人工智能项目】深度学习实现白葡萄酒品质预测
  17. 智能优化算法:寄生-捕食算法-附代码
  18. P2404 自然数的拆分问题(洛谷)
  19. 17.深入浅出:非正弦波发生电路——参考《模拟电子技术基础》清华大学华成英主讲
  20. 论系统的木桶理论与性能瓶颈

热门文章

  1. 升级TortoiseSVN-1.9.0.26652-x64-svn-1.9.0导致错误提示
  2. 修改ie9默认的quirk模式
  3. FileSystem close Exception
  4. golang 判断字符串是不是数字
  5. python3 操作redis
  6. linux c 指针 内存 泄漏几种情况
  7. python3 eval安全替代函数ast.literal_eval
  8. linux tail命令详解
  9. wifi密码破解与攻击
  10. Linux C 获取本地 ip mac 域名对应 ip