解析相对日期

时间:2016-12-26 10:09:19

标签: parsing datetime go

如何在GO中解析相对日期时间?

相对日期的例子:

today at 9:17 AM
yesterday at 9:58 PM
Saturday at 9:44 PM
Wednesday at 11:01 AM

因此格式为DAY (in the past) at TIME。我尝试了下一个例子:

const longForm = "Monday at 3:04 PM"
t, _ := time.Parse(longForm, "Saturday at 3:50 PM")
fmt.Println(t)

demo

正确解析时间,但忽略日期/日期......

3 个答案:

答案 0 :(得分:1)

扩展我的评论:

只有Monday没有进一步的日期引用在解析器的眼中是没有意义的,所以它被丢弃了。哪个星期一?解析器是严格的,而不是模糊的。假设星期一指的是当前周不是这样的解析器可以做的事情。你不会为此编写自己更复杂的解析器。

所以它必须沿着这些方向 - 一个将相对模糊日转换为实际日期的函数,并替换原始表达式中的函数,另一个函数解析整个事物:

const dateFormat = "2006-01-02"
const longForm = "2006-01-02 at 3:04 PM"

func parseFuzzyDate(fuzzyTime string) (time.Time, error) {

    formattedTime, err := parseDayAndReplaceIt(fuzzyTime)
    if err != nil {
       return nil, err
    }

    return time.Parse(longForm, formattedTime)
}

并且第二个函数获得模糊时间,找到日期,解析它并返回。我不打算实现它,只需在评论中写下应该做什么:

func parseDayAndReplaceIt(fuzzyTime string) (string, error) {
   // 1. Extract the day

   // 2. Parse weekday names to relative time

   // 3. if it's not a weekday name, parse things like "tomorrow" "yesterday"

   // 4. replace the day string in the original fuzzyTime with a formatted date that the parser can understand

   // 5. return the formatted date
}

答案 1 :(得分:0)

我调整了一段时间后写的东西并将其合并到这个示例代码中:

func lastDateOf(targetDay time.Weekday, timeOfDay time.Time) time.Time {
    const oneDay = 24 * time.Hour
    var dayIndex time.Duration

    //dayIndex -= oneDay
    for {
        if time.Now().Add(dayIndex).Weekday() == targetDay {
            y, m, d := time.Now().Add(dayIndex).Date()
            return timeOfDay.AddDate(y, int(m)-1, d-1)
        }
        dayIndex -= oneDay
    }
}

它返回上一个targetDay的相对于现在的日期,添加到timeOfDay,假设timeOfDay包含小时,分钟和秒,以及零时间值年,月,日它会给你一个合适的答案。

它不是很灵活,但我相信它很适合你的例子。虽然它没有涉及“明天”,“昨天”或“下周六”等相关术语。

playground中的可运行版本。

答案 2 :(得分:0)

自定义解析器:

func RelativeDateParse(s string) (time.Time, error) {
    for n := 0; n < 7; n++ {
        day := time.Now().AddDate(0, 0, -n)
        dayName := day.Format("Monday")
        switch n {
        case 0:
            dayName = "today"
        case 1:
            dayName = "yesterday"
        }
        s = strings.Replace(s, dayName + " at", day.Format("2006-01-02"), -1)
    }
    return time.Parse("2006-01-02 3:04 PM", s)
}

demo