首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将浮点数秒转换为秒,并将nanoOfSecond转换为java时间。

将浮点数秒转换为秒,并将nanoOfSecond转换为java时间。
EN

Stack Overflow用户
提问于 2022-09-23 17:07:37
回答 1查看 128关注 0票数 1

我有一个浮点值表示秒。我想将它分割成两个整数,表示整秒和纳秒,以便将它作为最后两个参数传递给java.time.ZonedDateTime.of()构造函数。

这是我目前的方法,但我担心我可能会不必要地失去精度,或者重新创建某种现有的java时功能:

代码语言:javascript
复制
;;seconds >= 0 and < 60
(defn seconds-and-nanos
  [seconds]
  (cond
    (integer? seconds) [seconds 0]
    (float? seconds) [(int seconds) (int (* (mod seconds (int seconds)) 1000000000))]))


;;repl> (seconds-and-nanos 3.4)
;;[3 399999999]

有更好的办法吗?谢谢你的帮助。

Update,这似乎工作得更好,但仍然好奇它是否可以改进:

代码语言:javascript
复制
;;seconds >= 0 and < 60
(defn seconds-and-nanos
  [seconds]
  (cond
    (integer? seconds)
    [seconds 0]
    
    (float? seconds)
    (let [whole (int seconds)
          nano (Math/round (* (- seconds whole) 1000000000))]
      (if (= nano 1000000000)
        [whole (- nano 1)]
        [whole nano]))))

;;repl> (seconds-and-nanos 3.4)
;;[3 400000000]
;;repl> (seconds-and-nanos 3.9999999999)
;;[3 999999999]
;;repl> (seconds-and-nanos 3.999999999)
;;[3 999999999]

更新2

根据已被接受的答案和评论,以及我自己对代码进行重新定位的一些经验,我合并为:

代码语言:javascript
复制
(defn seconds-and-nanos
  [seconds]
  (let [whole (long (Math/floor seconds))
        fraction (- seconds whole)
        nano (* fraction 1000000000)
        nano (cond
               (float? nano) (Math/round nano)
               (instance? clojure.lang.BigInt nano) (long nano)
               :else nano)]
    (if (= nano 1000000000)
      [whole (- nano 1)]
      [whole nano])))

seconds不再被限制在60或更少。if (= nano 1000000000)块与上下文高度相关,可以根据需要删除或重写;对于我的用例,我认为这是一种非常罕见的边缘情况(仅在某种程度上处理超出了nano精度的seconds时才出现,这已经令人怀疑),因此我决定走一条更加方便的路径,始终向下舍入,以避免添加整个第二个单元,并且可能会级联到每一个其他单元(分钟、小时等)。

谢谢你的帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-25 10:22:20

我将使用如下内容,从我最喜欢的模板项目开始

代码语言:javascript
复制
(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [schema.core :as s])
  (:import
    [java.time Instant]))

(def SECOND->NANOS 1.0e9)

(s/defn epoch-sec->Instant :- Instant
  "Accepts a floating point value of epoch second and converts to a java.time.Instant"
  [epoch-seconds :- s/Num]
  (assert (<= 0 epoch-seconds)) ; throw for negative times for simplicity
  (let [esec-dbl      (double epoch-seconds)
        esec-whole    (Math/floor esec-dbl)
        esec-fraction (- esec-dbl esec-whole)
        esec-nanos    (Math/round (* esec-fraction SECOND->NANOS))
        result        (Instant/ofEpochSecond (long esec-whole) (long esec-nanos))]
    result))

单元测试

代码语言:javascript
复制
(verify
  (throws? (epoch-sec->Instant -1))
  (is= "1970-01-01T00:00:00Z" (str (epoch-sec->Instant 0.0)))
  (is= "1970-01-01T00:00:00.100Z" (str (epoch-sec->Instant 0.1)))
  (is= "1970-01-01T00:00:00.999990Z" (str (epoch-sec->Instant 0.99999)))
  (is= "1970-01-01T00:00:00.999999900Z" (str (epoch-sec->Instant 0.9999999))))

然后,可以使用静态方法从Instant值构建ZDT。

代码语言:javascript
复制
static ZonedDateTime  ofInstant(Instant instant, ZoneId zone)

您可以为java.time 已经写在这里了找到大量的转换和方便函数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73830954

复制
相关文章

相似问题

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