2016-12-26 22 views
-2

如何在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

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

+0

'Monday'无需进一步日期参考是在分析器的眼睛没有意义的,因此它被丢弃。哪个星期一?你不会为此编写自己更复杂的解析器。 –

+0

@Not_a_Golfer:过去的第一个星期一,我已经在这个问题中写道:'所以格式是“天(过去)在TIME”。我尝试了下一个例子:' –

+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 
} 
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中的可运行版本。

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