【问题标题】:Converting timestamp to milli seconds since epoch将时间戳转换为自纪元以来的毫秒数
【发布时间】:2013-08-19 16:12:51
【问题描述】:

目前我正在逐行读取数据文件。每行都有一个时间戳,格式为 dd/MM/yyyy HH:mm:ss" 自纪元以来,我需要将其转换为毫秒。我尝试了两种方法

1> 使用标准库

timestamp  = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.ENGLISH).parse(ddMMyyyy + " " + HHmmss);
return timestamp.getTime();

2> 这是使用 Joda-Time 库

jiffy = format.parseMillis(ddMMyyyy + " " + HHmmss);

分析后,我发现方法一非常昂贵,而方法二比第一种便宜一点,但仍然很昂贵。第一个需要大约 1600 毫秒的 CPU 时间,第二个需要 1100 毫秒的 CPU 时间。

问题 -

1> 有没有比这更贵的图书馆?

2> 如果没有标准库,有人可以指出转换逻辑吗?我尝试谷歌搜索但没有成功。这个网站上的公式很少,但它们不起作用或让我们调用它然后它们不够简单。

谢谢

**

添加有关问题的更多详细信息

**

好的..在此处添加更多详细信息。 测试运行是针对 1000 万条记录。每行都有时间戳,需要从纪元开始转换为毫秒。

这是我尝试过的三个版本的代码。

1> 使用 Joda-Time - 迄今为止最好的结果,但不可接受。它花费 26.9% 的时间进行时间转换。

long jiffy = 0;
public double getTime( String ddMMyyyy, String HHmmss) throws ParseException
{       
    jiffy = format.parseMillis(ddMMyyyy + " " + HHmmss);
    return jiffy/1000;
}

这是分析 http://postimg.org/image/bvrt3esgr/

2> 带有 SimpleTimeFormat java 类。 如果一个人再次使用同一个对象,则完成此任务需要 36.1%。

private long timestamp;
public static final SimpleDateFormat SDF = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss",Locale.ENGLISH);
long jiffy = 0;

public double getTime( String ddMMyyyy, String HHmmss) throws ParseException
{
    timestamp = SDF.parse(ddMMyyyy + " " + HHmmss).getTime();
    return timestamp;
}

这是个人资料 http://postimg.org/image/72iua8x9j/ 3> 使用 SimpleTimeFormat java 类。 如果正在创建新对象,则执行此任务需要 51.6%。

public long getTimei( String ddMMyyyy, String HHmmss) throws ParseException
{
    timestamp  = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.ENGLISH).parse(ddMMyyyy + " " + HHmmss);
    return timestamp.getTime();
}

这是个人资料 postimg.org/image/rnp2m1c2r/

现在我的问题还是一样???

1> 有没有比这更贵的图书馆?

2> 如果没有标准库,有人可以指点我转换逻辑吗?我尝试谷歌搜索但没有成功。这个网站上的公式很少,但它们不起作用或让我们调用它然后它们不够简单。

【问题讨论】:

  • 1100 毫秒有多少个值? 2? 20亿?无论如何,从文件中读取行可能比解析日期要长得多(读取速度慢几个数量级),因此优化解析不会导致任何可测量的差异。
  • 如果你只测量一次,你的JVM没有预热。制定适当的基准。
  • 下面添加更多细节..

标签: java timestamp jodatime simpledateformat epoch


【解决方案1】:

有没有比这更贵的图书馆?

很有可能您不应该每次都创建一个新的 SimpleDateFormat 并且您忘记了先预热代码。我建议您在忽略前 10,000 次运行后运行测试至少 2 秒。

或者您可能将 (ns) 纳秒与 (ms) 毫秒混淆了。

public static final SimpleDateFormat SDF = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.ENGLISH);
static {
    SDF.setTimeZone(TimeZone.getTimeZone("GMT"));
}

public static void main(String[] args) throws Exception {
    String dateTime = SDF.format(new Date());

    long start = 0;
    int warmup = 10000;
    int runs = 1000000;
    for (int i = -warmup; i < runs; i++) {
        if (i == 0)
            start = System.nanoTime();
        long time = SDF.parse(dateTime).getTime();
        if (time < 0) throw new AssertionError();
    }
    long time = System.nanoTime() - start;
    System.out.printf("The average time to parse the current time was %,d nano-seconds%n", time / runs);
}

打印

The average time to parse the current time was 1,250 nano-seconds

如果 1250 纳秒不够快,您可以编写自己的解析器。我见过的最快的是 100 纳秒。

【讨论】:

    【解决方案2】:

    java.time

    处理此类时间转换的现代方法是使用 java.time 框架。我不知道它在执行速度或垃圾生成方面的表现如何,但应该考虑在内。

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormatJoda-Time 团队还建议迁移到 java.time。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

    大部分 java.time 功能在ThreeTen-Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中进一步适应 Android。

    示例代码

    您的问题未能解决时区问题。所以我会假设你的输入字符串是为UTC 设计的,并使用Instant 类。对于其他时区,请在 Stack Overflow 中搜索 ZonedDateTime

    Instant 类代表 UTC 时间轴上的一个时刻,分辨率高达纳秒。它的toEpochMilli 方法产生一个long 整数(64 位),计算自UTC 1970 第一刻以来的毫秒数。请注意,此方法可能会丢失数据,因为任何纳秒在截断为毫秒时都会丢失。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" );
    Instant instant = Instant.parse( yourInputStringGoesHere , formatter );
    long millisecondsSinceEpochOf1970 = instant.toEpochMilli();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 2012-03-08
      • 1970-01-01
      • 2021-03-01
      • 2018-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多