Go语言便捷的时间命令行工具

学习:便捷的时间工具 | Go 语言编程之旅 (eddycjy.com)

代码参考:go-programming-tour-book/tour: 《Go 语言编程之旅:一起用 Go 做项目》第一章:命令行程序(Command) (github.com)

先搭好架子,再具体实现!

接口的应用中也有这种思想,接口相当于先制定标准再具体实现;

搭好架子/制定标准:全局架构清晰;具体实现。

先看Go语言单词格式转换命令行工具 - KpHang - 博客园 (cnblogs.com),此篇是以上篇文章架构为基础的。

搭好架子

$ tree
.
├── cmd
│   ├── root.go
│   ├── time.go
│   └── word.go
├── internal
│   ├── timer
│   │   └── time.go
│   └── word
│       └── word.go
├── main.go

cmd/time.go,用于单词格式转换的子命令 time 的简单设置

var timeCmd = &cobra.Command{
	Use:   "time",
	Short: "时间格式处理",
	Long:  "时间格式处理",
	Run:   func(cmd *cobra.Command, args []string) {},
}

cmd/time.go在给time子命令,再设置两个子命令(对于root而言,就是子命令的子命令;)

  • time now
  • time calc
//  time now 子命令
var nowTimeCmd = &cobra.Command{
	Use:   "now",
	Short: "获取当前时间",
	Long:  "获取当前时间",
	Run: func(cmd *cobra.Command, args []string) {},
}

// time calc 子命令
var calculateTimeCmd = &cobra.Command{
	Use:   "calc",
	Short: "计算所需的时间",
	Long:  "计算所需的时间",
	Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
	timeCmd.AddCommand(nowTimeCmd)       // 把nowTimeCmd加入root的子命令timeCmd中;
	timeCmd.AddCommand(calculateTimeCmd) // time cal 子命令注册
}

cmd/root.go,用于创建根命令,将子命令加入根命令中

func init() {
  ...
	rootCmd.AddCommand(timeCmd) // 将创建的time子命令加入rootcmd
}
  • 关于init函数:

main包中导入cmd并使用cmd包:

import (
	"log"
	"github.com/KpiHang/tour/cmd"
)

var name string

func main() {
	err := cmd.Execute()
	if err != nil {
		log.Fatalf("cmd.Execute err : %v", err)
	}
}

详细设置time子命令

time子命令本身并没有设置参数,只需要对time nowtime calc子命令进行设置。

cmd/time.gotime now:

//  time now 子命令
var nowTimeCmd = &cobra.Command{
	Use:   "now",
	Short: "获取当前时间",
	Long:  "获取当前时间",
	Run: func(cmd *cobra.Command, args []string) {
		nowTime := timer.GetNowTime()
		// 第一个格式:通过调用 Format 方法设定约定的 2006-01-02 15:04:05 格式来进行时间的标准格式化。
		// 第二个格式:通过调用 Unix 方法返回 Unix 时间,就是我们通俗说的时间戳,其值为自 UTC 1970 年 1 月 1 日起经过的秒数。
		log.Printf("输出结果:%s, %d", nowTime.Format("2006-01-02 15:04:05"), nowTime.Unix())
	},
}

log.Printf(...)

  • 第一个格式:通过调用 Format 方法设定约定的 2006-01-02 15:04:05 格式来进行时间的标准格式化。
  • 第二个格式:通过调用 Unix 方法返回 Unix 时间,就是我们通俗说的时间戳,其值为自 UTC 1970 年 1 月 1 日起经过的秒数。

cmd/time.gotime calc:

// time calc 子命令
var calculateTimeCmd = &cobra.Command{
	Use:   "calc",
	Short: "计算所需的时间",
	Long:  "计算所需的时间",
	Run: func(cmd *cobra.Command, args []string) {
		var currentTimer time.Time
		var layout = "2006-01-02 15:04:05"
		if calculateTime == "" {
			currentTimer = timer.GetNowTime()
		} else {
			var err error
			space := strings.Count(calculateTime, " ")
			if space == 0 {
				layout = "2006-01-02"
			}
			if space == 1 {
				layout = "2006-01-02 15:04:05"
			}
			// 使用了 time.Local,会根据系统配置来设置时区,中国是UTC+8
			currentTimer, err = time.ParseInLocation(layout, calculateTime, time.Local)
			if err != nil {
				t, _ := strconv.Atoi(calculateTime)
				currentTimer = time.Unix(int64(t), 0)
			}
		}
		t, err := timer.GetCalulateTime(currentTimer, duration)
		if err != nil {
			log.Fatalf("timer.GetCalculateTime err: %v", err)
		}

		log.Printf("输出结果: %s, %d", t.Format(layout), t.Unix())
	},
}
  • 第21行,最开始使用的是time.Parse(),但是默认时区是UTC+0,而中国在东八区;

    			currentTimer, err = time.ParseInLocation(layout, calculateTime, time.Local)
    

功能入口

上面两个子命令,涉及到两个函数的具体实现:

timer.GetNowTime()
timer.GetCalulateTime(currentTimer, duration)

timer包放在internal包中。

internal包,Go中命名为internal的package或者目录,两点需要注意:

  1. 只有直接父级package,以及父级package的子孙package可以访问,其他的都不行,再往上的祖先package也不行。
  2. 父级package也只能访问internal package使用大写暴露出的内容,小写的不行。

在项目中不被复用,也不能被其他项目导入,仅被本项目内部使用的代码包即私有的代码包都应该放在internal文件夹下。该文件夹下的所有包及相应文件都有一个项目保护级别,即其他项目是不能导入这些包的,仅仅是该项目内部使用。

功能具体实现

$ tree
.
├── cmd
│   ├── root.go
│   ├── time.go
│   └── word.go
├── internal
│   ├── timer
│   │   └── time.go
│   └── word
│       └── word.go
├── main.go

internal/timer/time.go,功能的具体实现:

func GetNowTime() time.Time {
	return time.Now()
}

// 时间推算,计算当前时间+间隔时间;
func GetCalulateTime(currentTimer time.Time, d string) (time.Time, error) {
	duration, err := time.ParseDuration(d)
	// ParseDuration 方法用于在字符串中解析出 duration(持续时间),其支持的有效单位有"ns”, “us” (or “µ s”), “ms”, “s”, “m”, “h”,例如:“300ms”, “-1.5h” or “2h45m”。而在 Add 方法中,我们可以将其返回的 duration 传入,就可以得到当前 timer 时间加上 duration 后所得到的最终时间。
	if err != nil {
		return time.Time{}, err
	}

	return currentTimer.Add(duration), nil
}

posted @ 2022-11-18 10:44  KpHang  阅读(74)  评论(0编辑  收藏  举报