首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >保存Joda时间“`DateTime`”对象的最有效方法是什么?

保存Joda时间“`DateTime`”对象的最有效方法是什么?
EN

Stack Overflow用户
提问于 2014-10-24 12:10:03
回答 3查看 1.5K关注 0票数 3

我编写了一些Java软件,经常从Redis中保存和检索尤达-时间 DateTime对象。我现在只是序列化和反序列化对象。该软件读取对象的频率大约是它所写的的50倍。我还没有描述过序列化/反序列化Joda-Time对象的情况,但是在计算上,这个软件在负载下进行了很好的扩展,我对它的性能很满意。

没有很好地扩展的是内存的使用。序列化的Joda-Time对象非常大,一个相当大的Redis实例只需3天左右的客户数据,我就需要将其清除到磁盘上的关系数据库中。第二个问题是Redis自己的备份机制似乎难以管理更大的数据集.

撇开把更多RAM用于这个问题的诱惑放在一边,到目前为止,我想到了以下几个想法:

  • 序列化,然后在持久化之前压缩对象。
  • 持久化为ISO日期格式字符串
  • 保持为其他与Joda兼容的字符串格式。

在决定之前,我将尝试并分析这些内容,但我想知道是否有人能想出一种更有效的方法来减少持久化Joda对象的内存占用而不破坏计算库?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-26 08:43:18

ISO 8601

我对Redis…一无所知一般来说,序列化Joda-Time对象的最简单和最有效的方法是利用它们对日期时值的合理、明确、标准的ISO 8601字符串格式的内置支持。

对于分区日期时间值,标准提供了YYYY-MM-DDTHH:MM:SS.SSS±HH:SS格式,如2014-10-24T21:17:30+02:002014-10-24T19:17:30Z (Z For Zulu意味着与UTC的偏移量为00:00 )。

各种Joda-Time2.5类使用ISO 8601作为解析和生成日期时间值的字符串表示的默认值。

生成串

对于DateTime,只需显式或隐式地调用其toString方法即可。

代码语言:javascript
运行
复制
String output = DateTime.now( DateTimeZone.forID( "America/Montreal" ) ).toString();

通常最好在存储日期-时间值时使用UTC。Joda-Time让您轻松地适应UTC。

代码语言:javascript
运行
复制
DateTime nowMontreal = DateTime.now( DateTimeZone.forID( "America/Montreal" ) );
DateTime nowUtc = nowMontreal.withZone( DateTimeZone.UTC );
String output = nowUtc.toString();

另一个例子。

代码语言:javascript
运行
复制
DateTime output = DateTime.now( DateTimeZone.UTC ).toString();

解析字符串

解析也同样容易。唯一的问题是时区。如果省略时区,通常Joda-Time将分配JVM当前的默认时区。如果显式指定所需的时区,通常情况下会更好。

代码语言:javascript
运行
复制
DateTime dateTimeMontreal = new DateTime( "2014-10-24T19:17:30Z", DateTimeZone.forID( "America/Montreal" ) );

或者,UTC…

代码语言:javascript
运行
复制
DateTime dateTimeUtc = new DateTime( "2014-10-24T19:17:30Z", DateTimeZone.UTC ) );

java.time

另一种选择是在Java 8中内置的新java.time包。受Joda-Time的启发,java.time在许多方面都是相似的。但一个不同之处在于,java.time在默认情况下通过扩展ISO8601标准来生成字符串表示,以附加时区的名称。虽然标准格式具有与UTC的偏移量,但您可以松散实际的时区信息.(时区是一个偏移加上夏令节约时间的规则,以及现在、将来和过去的其他异常情况。)

另一方面,通常情况下,最好将日期时间存储在UTC.如果您真的关心数据输入时的时区,那么除了UTC调整后的值之外,通常最好单独存储这些信息。

在java.time中,Instant类表示UTC中时间线上的某个时刻。

代码语言:javascript
运行
复制
Instant instant = Instant.parse( "2014-10-24T19:17:30Z" );
String outputInstant = instant.toString();

2014-10-24T19:17:30 Z

若要调整到时区,请指定ZoneId以获得ZonedDateTime

代码语言:javascript
运行
复制
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
String outputZdt = zdt.toString();

2014-10-24T15:17:30-04:00美国/蒙特利尔

票数 4
EN

Stack Overflow用户

发布于 2014-10-26 09:21:06

尝试分析日期时间对象的分布。如果它们之间的距离相对较近,那么你可以做一些“魔法”:

1)您可以引入一个特殊的“起始日期”常量,然后将实际日期存储为与常量相移的天数--即整数值(64位arch上的~8字节)。w/o压缩)

2)你需要实际时间吗?如果不是,只需浪费时间;如果是,则可以将hours+minutes+seconds存储在一个int变量中(64位arch上的另一个~8字节)。w/o压缩)

3)分析结果--在单个int变量中,有可能同时适用日期(移位)和时间。

4)引入缓存机制,这将大大提高序列化/反序列化对象的性能。

票数 1
EN

Stack Overflow用户

发布于 2019-05-21 09:32:56

从时代开始就储存米利斯。这是一个单一的长值。如果您需要一个时区值,也可以将时区Id存储为字符串。序列化和解析字符串表示总是需要更多的资源,包括RAM、内部的大量数据处理、一些正则表达式、分配更多内存的拆分调用。

使用这个构造函数来恢复值:public BaseDateTime(long instant, DateTimeZone zone),它非常轻巧,因为它存储在每个DateTime实例的遮罩下:

代码语言:javascript
运行
复制
public BaseDateTime(long instant, Chronology chronology) {
        super();
        iChronology = checkChronology(chronology);
        iMillis = checkInstant(instant, iChronology);
        adjustForMinMax();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26547596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档