Преобразование строк в Core.Time.t из строки формата

Я должен конвертировать строки в форме %d/%m/%Y %H:%M:%S к времени Есть ли основной эквивалент календаря Printer.Time.from_fstring функционировать?

1 ответ

Решение

Базовая версия

Насколько я знаю, такой функции в Core библиотека. Вы можете легко реализовать это, используя scanf:

open Core.Std

let of_parts d m y hr min sec =
  let time_of_day = Time.Ofday.create ~hr ~min ~sec () in
  let m = Month.of_int_exn m in
  let date = Date.create_exn ~y ~m ~d in
  Time.of_date_ofday date time_of_day ~zone:Time.Zone.utc

let strptime0 data =
  Scanf.sscanf data "%d/%d/%d %d:%d:%d" of_parts

Полная версия

strptime0 является первым приближением, которое будет анализировать ввод с фиксированным форматом. Это не очень сложно реализовать strptime функция, которая примет формат. Для этого нам необходимо выполнить следующие шаги:

Преобразовать строку формата

Прежде всего нам нужно преобразовать строку формата из strptime язык для форматирования языка, например, для преобразования %Y -> %4dи т. д., а затем использовать Scanf.format_from_string получить экземпляр format объект. Возвращаемым значением этой функции должен быть формат, подходящий для scanf, и матрица перестановок, закодированная в виде массива.

Переставить аргументы

Вы можете использовать массив, чтобы указать порядок элементов:

(** [rearrage f p a0 a1 a2 a3 a4 a5] call function [f] with
    provided arguments passed in the order specified by the
    permutation [p]

    The [i]th element of the permutation [p] specifies the subscript
    of the [i]'th argument to function [f]. Effectively [f] is called
    like this: $f a_{p[0]} ... a_{p[i]} ... a_{p[5]}$ *)

let rearrange f arr a1 a2 a3 a4 a5 a6 =
  let args = [| a1; a2; a3; a4; a5; a6 |] in
  f args.(arr.(0)) args.(arr.(1)) args.(arr.(2))
    args.(arr.(3)) args.(arr.(4)) args.(arr.(5))

(это будет работать нормально, если мы представим все части целыми числами, как только мы введем аргументы с плавающей запятой (для %S нам нужно поднять аргументы в наш собственный тип нумерации).

Склеить

Так что, наконец, вы получите что-то вроде этого (вам все равно нужно заполнить заглушки)

(* d m y hr min sec *)
let canonical_format = format_of_string "%d%d%d%d%d%d"

(* this is a stub, that doesn't support rearrangment
   and works incorrectly for most of inputs *)
let fmt_of_time p = function
  | 'm' | 'Y' | 'H' | 'M' | 'S' -> 'd'
  | x -> x

let transform_format fmt =
  let p = Array.init 6 ~f:ident in (* stub: identity permutation *)
  let fmt = String.map fmt ~f:(fmt_of_time p) in
  let fmt = Scanf.format_from_string fmt canonical_format in
  p, fmt

let strptime data fmt =
  let (p,fmt) = transform_format fmt in
  let of_parts = rearrange of_parts p in
  Scanf.sscanf data fmt of_parts

Итак, в результате мы можем сделать следующее:

# strptime "09/05/1945 12:04:32" "%d/%m/%Y %H:%M:%S";;
- : Core.Std.Time.t = 1945-05-09 08:04:32.000000-04:00
Другие вопросы по тегам