Хранение и получение микросекунд из DA.Time

Я работаю с временной меткой FIX 20180605-03:10:33.0240756, которую мне нужно преобразовать в DA.Time, чтобы она сохранялась как часть торговой информации. Мне также нужно вернуть микросекунды как часть ответного сообщения (ACK/NACK).

В идеале я хотел бы иметь простой способ сделать это.

В настоящее время я сохраняю только секунды, используя конструктор времени DA.Time. Глядя на https://docs.daml.com/daml/stdlib/base.html#data-prelude-time-24894, похоже, микросекунды можно получить следующим образом:

  1. создание другого времени без микросекунд
  2. subTime оба, чтобы получить RelTime
  3. позвони microseconds в RelTime

Пожалуйста, сообщите, правильно ли это, если есть лучший способ сделать это. Спасибо.


person blu35ky    schedule 13.05.2019    source источник


Ответы (1)


При обычных обстоятельствах я бы порекомендовал выполнять синтаксический анализ строки вне реестра и передавать даты и время в виде типов Date и Time, но похоже, что у вас есть требование сделать это в реестре в DAML.

Ваш первый вопрос касается синтаксического анализа строки в DA.Time. В настоящее время нет встроенной функции синтаксического анализа даты/времени общего назначения, поэтому вам придется создать свою собственную. Для фиксированного формата, такого как ваш, сопоставление с образцом делает это довольно просто:

daml 1.2
module ParseTime where

import DA.Assert
import DA.Optional
import DA.Text
import DA.Time
import DA.Date

-- | `parseUTC` takes a string in the format "yyyyMMdd-HHmmss.SSS"
-- and converts it to `Time`, assuming the time is in UTC
-- Time is truncated to whole microseconds.
parseDateTimeUTC utc = datetime yy mon dd h m s `addRelTime` micros
  where
    -- Split out the micro seconds to stay under
    -- pattern match complexity limit
    [dt, ms] = splitOn "." utc
    -- Pattern match on `explode` to check
    -- the format and assign names to characters
    [ y1, y2, y3, y4, mon1, mon2, d1, d2, "-",
      h1, h2, ":", m1, m2, ":", s1, s2
      ] = explode dt
    -- The function will fail on `fromSome` if any of the
    -- integer strings don't parse
    unsafeParse = fromSome . parseInt . implode
    -- Map the parse function over grouped characters and
    -- pattern match the result to give names to the Ints
    [yy, imon, dd, h, m, s, imic] = map unsafeParse
      [[y1, y2, y3, y4], [mon1, mon2], [d1, d2],
      [h1, h2], [m1, m2], [s1, s2], explode $ T.take 6 ms]
    -- Process month and microseconds into `Month` and
    -- `Reltime` types
    mon = toEnum $ imon - 1
    mic = 10 ^ (max 0 (6 - T.length ms)) * imic
    micros = convertMicrosecondsToRelTime mic

t = scenario do
  let t = time (date 2018 Jun 05) 03 10 33 `addRelTime` convertMicrosecondsToRelTime 24075
  parseDateTimeUTC "20180605-03:10:33.0240756" === t

Для перехода между DA.Time и микросекундами нам нужно сделать выбор часового пояса. Предполагая UTC, мы можем определить

epochUTC = datetime 1970 Jan 1 0 0 0
microToTimeUTC n = epoch `addRelTime` convertMicrosecondsToRelTime n
timeToMicroUTC t = convertRelTimeToMicroseconds $ t `subTime` epoch

t2 = scenario do
  microToTimeUTC 1557733583000000 === datetime 2019 May 13 07 46 23
  timeToMicroUTC (datetime 2019 May 13 07 46 23) === 1557733583000000

для перехода между DA.Time и Int представлениями дат.

Если вам нужна микросекундная составляющая существующего DA.Time, вам нужны только последние шесть цифр микросекундного представления:

micros t = timeToMicroUTC t % 1000000

t3 = scenario do
  micros (parseDateTimeUTC "20180605-03:10:33.0240756") === 24075

Обратите внимание на усечение до целых микросекунд, это также упоминается в описании parseDateTimeUTC.

person bame    schedule 13.05.2019