Гибкий разбор даты и времени в Go - PullRequest
2 голосов
/ 30 мая 2019

В дополнение к этому вопросу я хочу проанализировать дату / время, переданные в командной строке, в программу Go.На данный момент я использую пакет flag для заполнения строковой переменной ts, а затем следующий код:

if ts == "" {
    config.Until = time.Now()
} else {
    const layout = "2006-01-02T15:04:05"
    if config.Until, err = time.Parse(layout, ts); err != nil {
        log.Errorf("Could not parse %s as a time string: %s. Using current date/time instead.", ts, err.Error())
        config.Until = time.Now()
    }
}

Это работает нормально, если пользователь передает точно правильный формат - например, 2019-05-20T09:07:33 или что-то подобное.

Тем не менее, я хотел бы, если это возможно, гибкость передачи, например, 2019-05-20T09:07 или 2019-05-20T09 или, может быть, даже 2019-05-20 и для часов, минут и секунд по умолчанию 0, где это необходимо.

Есть ли вменяемый 1 способ сделать это?


1 , не требующий от меня написания собственного парсера


ОБНОВЛЕНИЕ

У меня вроде есть решение для этого, хотя оно не особенно элегантно, похоже, оно работает для большинства случаев, с которыми я могу столкнуться.

package main

import (
    "fmt"
    "time"
)

func main() {

    const layout = "2006-01-02T15:04:05"
    var l string
    var input string

    for _, input = range []string{"2019-05-30", "2019-05-30T16", "2019-05-30T16:04", "2019-05-30T16:04:34",
                                "This won't work", "This is extravagantly long and won't work either"} {
        if len(input) < len(layout) {
            l = layout[:len(input)]
        } else {
            l = layout
        }
        if d, err := time.Parse(l, input); err != nil {
            fmt.Printf("Error %s\n", err.Error())
        } else {
            fmt.Printf("Layout %-20s gives time %v\n", l, d)
        }
    }
}

Ответы [ 3 ]

2 голосов
/ 30 мая 2019

Я думаю, что эта библиотека - то, что вы ищете https://github.com/araddon/dateparse

Разобрать много строк дат, не зная заранее формат. Использует сканер для чтения байтов и использует конечный автомат для поиска формата.

t, err := dateparse.ParseAny("3/1/2014")
2 голосов
/ 30 мая 2019

Просто попробуйте каждый формат, пока один не работает.Если ничего не работает, верните ошибку.

var formats = []string{"2006-01-02T15:04:05", "2006-01-02", ...}

func parseTime(input string) (time.Time, error) {
    for _, format := range formats {
        t, err := time.Parse(format, input)
        if err == nil {
            return t, nil
        }
    }
    return time.Time{}, errors.New("Unrecognized time format")
}
1 голос
/ 30 мая 2019

В конкретном сценарии, который вы описываете, вы можете проверить длину строки входной метки даты и добавить в конце правильную длину нуля, чтобы она соответствовала вашему layout.Таким образом, вы можете добавить к входу столько строк "T00:00:00" (считая от конца), сколько не хватает по сравнению со строкой формата layout.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...