相对日期解析

huangapple go评论82阅读模式
英文:

Relative date parsing

问题

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

相对日期的示例:

<!-- language: none -->

今天上午9:17
昨天晚上9:58
星期六晚上9:44
星期三上午11:01

所以格式是DAY (过去的时间) at TIME。我尝试了下面的示例:

<!-- language: go -->

const longForm = "星期一上午3:04"
t, _ := time.Parse(longForm, "星期六下午3:50")
fmt.Println(t)

<kbd>演示</kbd>

时间被正确解析,但是日期被忽略了...

英文:

How to parse relative datetime in GO?

Example of relative dates:

<!-- language: none -->

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

So format is DAY (in the past) at TIME. I tried next example:

<!-- language: go -->

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

<kbd>demo</kbd>

Time is parsed correctly, but day/date is ignored...

答案1

得分: 1

扩展我的评论:

只有“星期一”而没有进一步的日期参考对解析器来说是没有意义的,所以它被丢弃了。哪个星期一?解析器是严格的,不是模糊的。假设星期一指的是当前的一周是不可能的。你需要自己编写一个更复杂的解析器。

所以它应该按照以下方式进行 - 一个函数将相对模糊的日期转换为实际日期,并将其替换在原始表达式中,另一个函数解析整个内容:

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. 提取日期
   
   // 2. 将星期几的名称解析为相对时间
   
   // 3. 如果不是星期几的名称,解析类似“明天”、“昨天”的内容
   
   // 4. 用解析器可以理解的格式化日期替换原始模糊时间中的日期字符串
   
   // 5. 返回格式化的日期
}
英文:

Expanding on my comment:

Just Monday without further date reference is meaningless in the eyes of the parser, so it is discarded. Which Monday? The parser is strict, not fuzzy. Assuming Monday refers to the current week is not something that such a parser can do. You will not to write your own more sophisticated parser for that.

So it would have to be along these lines - one function that converts a relative fuzzy day to a real date, and replaces that in the original expression, and another one that parses the whole thing:

const dateFormat = &quot;2006-01-02&quot;
const longForm = &quot;2006-01-02 at 3:04 PM&quot;

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

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

    return time.Parse(longForm, formattedTime)
}

and the second function gets the fuzzy time, finds the day, parses it and returns. I'm not going to implement it, just write in comments what should be done:

func parseDayAndReplaceIt(fuzzyTime string) (string, error) {
   // 1. Extract the day
   
   // 2. Parse weekday names to relative time

   // 3. if it&#39;s not a weekday name, parse things like &quot;tomorrow&quot; &quot;yesterday&quot;

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

答案2

得分: 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 上有可运行的版本。

英文:

I tweaked something that I wrote a while back and consolidated it into this example code:

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
	}
}

It returns the date, relative to now, of the previous targetDay, added to timeOfDay, assuming that timeOfDay consists of hours, minutes and seconds, and the zero time values for year, month and day it will give you a suitable answer.

It's not very flexible but I believe it suits your example reasonably well. Although it doesn't address relative terms like "tomorrow", "yesterday" or "next Saturday".

runnable version in the playground.

答案3

得分: 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 = "今天"
        case 1:
            dayName = "昨天"
        }
        s = strings.Replace(s, dayName + " at", day.Format("2006-01-02"), -1)
    }
    return time.Parse("2006-01-02 3:04 PM", s)
}

<kbd>[**演示**][1]</kbd>


  [1]: https://play.golang.org/p/ibOU4KcuSi
英文:

Custom parser:

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

<kbd>demo</kbd>

huangapple
  • 本文由 发表于 2016年12月26日 18:09:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/41329583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定