Go每日一库之dateparse处理时间

目录
  • 简介
  • 快速使用
  • 格式
  • 时区
  • cli
  • 总结
  • 参考

简介

不管什么时候,处理时间总是让人头疼的一件事情。因为时间格式太多样化了,再加上时区,夏令时,闰秒这些细枝末节处理起来更是困难。所以在程序中,涉及时间的处理我们一般借助于标准库或第三方提供的时间库。今天要介绍的dateparse专注于一个很小的时间处理领域——解析日期时间格式的字符串。

快速使用

本文代码使用 Go Modules。

创建目录并初始化:

$ mkdir dateparse && cd dateparse
$ go mod init github.com/darjun/go-daily-lib/dateparse

安装dateparse库:

$ go get -u github.com/araddon/dateparse

使用:

package main

import (
  "fmt"
  "log"
  "github.com/araddon/dateparse"
)

func main() {
  t1, err := dateparse.ParseAny("3/1/2014")
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(t1.Format("2006-01-02 15:04:05"))

  t2, err := dateparse.ParseAny("mm/dd/yyyy")
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(t2.Format("2006-01-02 15:04:05"))
}

ParseAny()方法接受一个日期时间字符串,解析该字符串,返回time.Time类型的值。如果传入的字符串dateparse库无法识别,则返回一个错误。上面程序运行输出:

$ go run main.go
2014-03-01 00:00:00
2021/06/24 14:52:39 Could not find format for "mm/dd/yyyy"
exit status 1

需要注意,当我们写出"3/1/2014"这个时间的时候,可以解释为2014年3月1日,也可以解释为2014年1月3日。这就存在二义性,dateparse默认采用mm/dd/yyyy这种格式,也就是2014年3月1日。我们也可以使用ParseStrict()函数让这种具有二义性的字符串解析失败:

func main() {
  t, err := dateparse.ParseStrict("3/1/2014")
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(t.Format("2006-01-02 15:04:05"))
}

运行:

$ go run main.go
2021/06/24 14:57:18 This date has ambiguous mm/dd vs dd/mm type format
exit status 1

格式

dateparse支持丰富的日期时间格式,基本囊括了所有常用的格式。它支持标准库time中预定义的所有格式:

// src/time/format.go
const (
  ANSIC       = "Mon Jan _2 15:04:05 2006"
  UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
  RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
  RFC822      = "02 Jan 06 15:04 MST"
  RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
  RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
  RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
  RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
  RFC3339     = "2006-01-02T15:04:05Z07:00"
  RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
  Kitchen     = "3:04PM"
  // Handy time stamps.
  Stamp      = "Jan _2 15:04:05"
  StampMilli = "Jan _2 15:04:05.000"
  StampMicro = "Jan _2 15:04:05.000000"
  StampNano  = "Jan _2 15:04:05.000000000"
)

支持的完整格式查看dateparse README

时区

dateparse支持在特定时区解析日期时间字符串。我们可以通过调用标准库的time.LoadLocation()方法,传入时区标识字符串来获得时区对象。时区标识字符串是类似Asia/Shanghai,America/Chicago这样的格式,它表示一个具体的时区,前者上海,后者洛杉矶。调用dateparse.ParseIn()方法传入时区对象,在指定时区中解析。time包中还预定义了两个时区对象,time.Local表示本地时区,time.UTC表示 UTC 时区。时区的权威数据请看IANA。

func main() {
  tz1, _ := time.LoadLocation("America/Chicago")
  t1, _ := dateparse.ParseIn("2021-06-24 15:50:30", tz1)
  fmt.Println(t1.Local().Format("2006-01-02 15:04:05"))

  t2, _ := dateparse.ParseIn("2021-06-24 15:50:30", time.Local)
  fmt.Println(t2.Local().Format("2006-01-02 15:04:05"))
}

运行:

$ go run main.go
2021-06-25 04:50:30
2021-06-24 15:50:30

美国洛杉矶时区的"2021年6月24日 15时30分30秒"等于本地时区(北京时间)的"2021年6月25日 04时50分30秒"。

cli

dateparse还提供了一个命令行工具,用于极快地查看日期时间格式。安装:

$ go install github.com/araddon/dateparse/dateparse

默认会安装在$GOPATH路径下,我习惯上把$GOPATH/bin放到$PATH中。所以dateparse命令可以直接使用。
dateparse命令接收一个字符串,和一个可选的时区选项:

$ dateparse --timezone="Asia/Shanghai" "2021-06-24 06:46:08"

Your Current time.Local zone is CST

Layout String: dateparse.ParseFormat() => 2006-01-02 15:04:05

Your Using time.Local set to location=Asia/Shanghai CST

+-------------+---------------------------+-------------------------------+-------------------------------------+
| method      | Zone Source               | Parsed                        | Parsed: t.In(time.UTC)              |
+-------------+---------------------------+-------------------------------+-------------------------------------+
| ParseAny    | time.Local = nil          | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC day=4 |
| ParseAny    | time.Local = timezone arg | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC day=4 |
| ParseAny    | time.Local = time.UTC     | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC day=4 |
| ParseIn     | time.Local = nil          | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
| ParseIn     | time.Local = timezone arg | 2021-06-24 06:46:08 +0800 CST | 2021-06-23 22:46:08 +0000 UTC       |
| ParseIn     | time.Local = time.UTC     | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
| ParseLocal  | time.Local = nil          | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
| ParseLocal  | time.Local = timezone arg | 2021-06-24 06:46:08 +0800 CST | 2021-06-23 22:46:08 +0000 UTC       |
| ParseLocal  | time.Local = time.UTC     | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
| ParseStrict | time.Local = nil          | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
| ParseStrict | time.Local = timezone arg | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
| ParseStrict | time.Local = time.UTC     | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC       |
+-------------+---------------------------+-------------------------------+-------------------------------------+

输出当前本地时区,格式字符串(可用于生成同样格式的日期时间字符串)和一个表格。表格里面的数据是分别对ParseAny/ParseIn/ParseLocal/ParseStrict在不同的时区下调用的结果。

method列表示调用的方法,Zone Source列表示将本地时区设置的值,Parsed列是以日期时间字符串调用ParseAny()返回的time.Time对象的Format()方法调用结果,Parsed: t.In(time.UTC)列在返回的time.Time对象调用Format()方法前将其转为 UTC 时间。

由于ParseAny/ParseStrict不会考虑本地时区,都是在 UTC 下解析字符串,所以这 6 行的最后两列结果都一样。

ParseIn的第二行,将time.Local设置为我们通过命令行选项设置的时区,上面我设置为Asia/Shanghai,对应的 UTC 时间相差 8 小时。ParseLocal也是如此。

下面是dateparse命令行的部分源码,可以对照查看:

func main() {
  parsers := map[string]parser{
    "ParseAny":    parseAny,
    "ParseIn":     parseIn,
    "ParseLocal":  parseLocal,
    "ParseStrict": parseStrict,
  }

  for name, parser := range parsers {
    time.Local = nil
    table.AddRow(name, "time.Local = nil", parser(datestr, nil, false), parser(datestr, nil, true))
    if timezone != "" {
      time.Local = loc
      table.AddRow(name, "time.Local = timezone arg", parser(datestr, loc, false), parser(datestr, loc, true))
    }
    time.Local = time.UTC
    table.AddRow(name, "time.Local = time.UTC", parser(datestr, time.UTC, false), parser(datestr, time.UTC, true))
  }
}

func parseIn(datestr string, loc *time.Location, utc bool) string {
  t, err := dateparse.ParseIn(datestr, loc)
  if err != nil {
    return err.Error()
  }
  if utc {
    return t.In(time.UTC).String()
  }
  return t.String()
}

注意输出的本地时区为 CST,它可以代表不同的时区:

Central Standard Time (USA) UT-6:00
Central Standard Time (Australia) UT+9:30
China Standard Time UT+8:00
Cuba Standard Time UT-4:00

CST 可以同时表示美国、澳大利亚、中国和古巴四个国家的标准时间。

总结

使用dateparse可以很方便地从日期时间字符串中解析出时间对象和格式(layout)。同时dateparse命令行可以快速的查看和转换相应时区的时间,是一个非常不错的小工具。

大家如果发现好玩、好用的 Go 语言库,欢迎到 Go 每日一库 GitHub 上提交 issue😄

参考

dateparse GitHub:https://github.com/araddon/dateparse
Go 每日一库 GitHub:https://github.com/darjun/go-daily-lib

到此这篇关于Go每日一库之dateparse处理时间的文章就介绍到这了,更多相关Go dateparse处理时间内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • go语言计算两个时间的时间差方法

    本文实例讲述了go语言计算两个时间的时间差方法.分享给大家供大家参考.具体分析如下: go语言计算两个时间的时间差,代码很简单,返回1天前.1周前还是1月前的时间 package main import ( "fmt" "time" ) func main() { //Add方法和Sub方法是相反的,获取t0和t1的时间距离d是使用Sub //将t0加d获取t1就是使用Add方法 k := time.Now() //一天之前 d, _ := time.ParseDu

  • go时间/时间戳操作大全(小结)

    基本操作 01: 获取当前时间 dateTime := time.Now() fmt.Println(dateTime) 02: 获取年 月 日 时 分 秒 纳秒 year := time.Now().Year() //年 fmt.Println(year) month := time.Now().Month() //月 fmt.Println(month) day := time.Now().Day() //日 fmt.Println(day) hour := time.Now().Hour(

  • Golang获取当前时间代码

    golang中时间相关操作,主要是用time包的函数,time中最主要又包含了time.Time这个对象. 1.获取当前时间 (1) currentTime:=time.Now()     //获取当前时间,类型是Go的时间类型Time (2) t1:=time.Now().Year()        //年     t2:=time.Now().Month()       //月     t3:=time.Now().Day()         //日     t4:=time.Now().H

  • Go实现比较时间大小

    先把当前时间格式化成相同格式的字符串,然后使用time的Before, After, Equal 方法即可. time1 := "2015-03-20 08:50:29" time2 := "2015-03-21 09:04:25" //先把时间字符串格式化成相同的时间类型 t1, err := time.Parse("2006-01-02 15:04:05", time1) t2, err := time.Parse("2006-01

  • Golang记录、计算函数执行耗时、运行时间的一个简单方法

    先写一个公共函数, 比如在 common 包下有这么一个方法: // 写超时警告日志 通用方法 func TimeoutWarning(tag, detailed string, start time.Time, timeLimit float64) { dis := time.Now().Sub(start).Seconds() if dis > timeLimit { log.Warning(log.CENTER_COMMON_WARNING, tag, " detailed:&quo

  • golang时间、时区、格式的使用方法

    前几天,因为需要实现海外服务端定时停机,涉及到时区的概念.网上搜索了一下,大部分都是谈time.Format中的Layout,非常不成体系,这里就简单总结一下其中的时间初始化.时区转化及格式转换. 开发中,我们对时间的使用是比较多的,其应用场景,按照使用概率,从大到小,通常是: 获取当前或数据库中存储的时间 比较两个时间点的先后 显示打印时间 时区转换 对应到go,也就是几个基本定义: 时间点与时间段:Time,Duration.好比MVC中的M. 时 区:Location,在时间转换上,好比是

  • go语言中时间戳格式化的方法

    本文实例讲述了go语言中时间戳格式化的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: var t int64 = time.Now().Unix() var s string = time.Unix(t, 0).Format("2006-01-02 15:04:05") println(s) 这方式比较特别,按照123456来记忆吧:01月02号 下午3点04分05秒 2006年 希望本文所述对大家的Go语言程序设计有所帮助.

  • Go每日一库之dateparse处理时间

    目录 简介 快速使用 格式 时区 cli 总结 参考 简介 不管什么时候,处理时间总是让人头疼的一件事情.因为时间格式太多样化了,再加上时区,夏令时,闰秒这些细枝末节处理起来更是困难.所以在程序中,涉及时间的处理我们一般借助于标准库或第三方提供的时间库.今天要介绍的dateparse专注于一个很小的时间处理领域--解析日期时间格式的字符串. 快速使用 本文代码使用 Go Modules. 创建目录并初始化: $ mkdir dateparse && cd dateparse $ go mo

  • Go 每日一库之termtables的使用

    目录 快速使用 模式 总结 今天学个简单点的

  • Go每日一库之quicktemplate的使用

    目录 简介 快速使用 语法结构 变量 调用函数 Web 总结 参考 简介 最近在整理我们项目代码的时候,发现有很多活动的代码在结构和提供的功能上都非常相似.为了方便今后的开发,我花了一点时间编写了一个生成代码框架的工具,最大程度地降低重复劳动.代码本身并不复杂,且与项目代码关联性较大,这里就不展开介绍了.在这个过程中,我发现 Go 标准的模板库text/template和html/template使用起来比较束手束脚,很不方便.我从 GitHub 了解到quicktemplate这个第三方模板库

  • Python使用arrow库优雅地处理时间数据详解

    前言 大家应该都知道在很多时候我们不得不和时间打交道,但在Python标准库中处理时间的模块其实设计的不是很友好,为什么我会这么说?因为我相信大部分人几乎每次在处理时间数据时一而再,再而三的去查文档,比如时间和文本格式互转,时间增减等看起来非常基本的操作,在Python中处理起来并不简单. 最要命的是,在Python标准库中居然有两个模块处理时间,一个叫time,另外一个叫datetime,里面提供了类似的方法但是两个完全不是一回事.到这还没完,标准库里还有一个叫calendar的模块,也是用来

  • Go位集合相关操作bitset库安装使用

    目录 简介 安装 使用 为什么要使用它? 总结 一点闲话 参考 简介 我们都知道计算机是基于二进制的,位运算是计算机的基础运算.位运算的优势很明显,CPU 指令原生支持.速度快.基于位运算的位集合在有限的场景中替换集合数据结构可以收到意想不到的效果.bitset库实现了位集合及相关操作,不妨拿来即用. 安装 本文代码使用 Go Modules. 创建目录并初始化: $ mkdir -p bitset && cd bitset $ go mod init github.com/darjun/

  • Go语言测试库testify使用学习

    目录 简介 准备工作 assert Contains DirExists ElementsMatch Empty EqualError EqualValues Error ErrorAs ErrorIs 逆断言 Assertions 对象 require mock suite 测试 HTTP 服务器 总结 简介 testify可以说是最流行的(从 GitHub star 数来看)Go 语言测试库了.testify提供了很多方便的函数帮助我们做assert和错误信息输出.使用标准库testing,

  • Go gorilla/sessions库安装使用

    目录 简介 快速使用 cookie 存储 记录登录状态 第三方后端存储 总结 简介 上一篇文章<Go 每日一库之 securecookie>中,我们介绍了 cookie.同时提到 cookie 有两个缺点,一是数据不宜过大,二是安全问题.session 是服务器端的存储方案,可以存储大量的数据,而且不需要向客户端传输,从而解决了这两个问题. 但是 session 需要一个能唯一标识用户的 ID,这个 ID 一般存放在 cookie 中发送到客户端保存,随每次请求一起发送到服务器.cookie

  • Go gorilla securecookie库的安装使用详解

    目录 简介 快速使用 使用 JSON 自定义编解码 Hash/Block 函数 更换 Key 总结 简介 cookie 是用于在 Web 客户端(一般是浏览器)和服务器之间传输少量数据的一种机制.由服务器生成,发送到客户端保存,客户端后续的每次请求都会将 cookie 带上.cookie 现在已经被多多少少地滥用了.很多公司使用 cookie 来收集用户信息.投放广告等. cookie 有两大缺点: 每次请求都需要传输,故不能用来存放大量数据: 安全性较低,通过浏览器工具,很容易看到由网站服务器

  • go goth封装第三方认证库示例详解

    目录 简介 快速使用 更换 store 总结 简介 当前很多网站直接采用第三方认证登录,例如支付宝/微信/ Github 等.goth封装了接入第三方认证的方法,并且内置实现了很多第三方认证的实现: 图中截取的只是goth支持的一部分,完整列表可在其GitHub 首页查看. 快速使用 本文代码使用 Go Modules. 创建目录并初始化: $ mkdir goth && cd goth $ go mod init github.com/darjun/go-daily-lib/goth 安

  • 使用Redis实现用户积分排行榜的教程

    排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择. 一般排行榜都是有实效性的,比如"用户积分榜".如果没有实效性一直按照总榜来排,可能榜首总是几个老用户,对于新用户来说,那真是太令人沮丧了. 首先,来个"今日积分榜"吧,排序规则是今日用户新增积分从多到少. 那么用户增加积分时,都操作一下记录当天积分增加的有序集合. 假设今天是 2015 年 04 月 01 日,UID 为 1 的用户因为某个操作,增加了 5 个积分. Re

随机推荐