重构之美-GO语言通用日期格式转换工具: 当2006-01-02 15:04:05遇上yyyy-MM-dd 等格式改何去何从

文章目录

最近公司技术转型到GO语言,语言外行的我看到项目一堆日期格式化都是采用2006-01-02 15:04:05
充斥大量篇幅,阅读极为不爽,没办法这是那GO语言那3个大佬敲定设计go语言IDEA,人家自然期望在自己语言里纪念这个日期,也无可厚非,你以后有机会写编程语言,写个xxxnb才能调用函数都没人拿你啥办法

Talk is cheap,咱还是考虑怎么从变成习惯上解决掉这个不爽的感觉,本篇的核心就是狸猫换太子, 顺便说一下,本文是一个通用解决的办法可以cover一切模版诸如:yyyy-MM-dd yyyy/MM/dd .etc


以简洁使用方便为目的,构造如下轮子,使用起来还是蛮香的,具体使用可以看如下的用例


package main
import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
)
const (
	DASH       = "-"
	UNDERLINE  = "_"
	DOT        = ","
	EQUALS     = "="
	SLASH      = "/"
	BACK_SLASH = "\\"
	SPACE      = " "
	COLON      = ":"
	EMPTY	   = ""
)
var standDateTimeTemplate = "2006%s01%s02 15%s04%s05"

func GetStrByTime(time time.Time) string {
	// yyyy-MM-dd HH:mm:ss
	split := getStrByTimeWithSplit(DASH, COLON)
	return getStrWithFormat(time, split)
}

func GetStrByTimeWithFormat(time time.Time, dateSpilt, timeSpilt interface{}) string {
	split := getStrByTimeWithSplit(dateSpilt, timeSpilt)
	return getStrWithFormat(time, split)
}

/**
 * 获取精确到毫秒的日期格式
 */
func GetMilliStrByTimeWithFormat(time time.Time, dateSpilt, timeSpilt interface{}) string {
	split := getStrByTimeWithSplit(dateSpilt, timeSpilt)
	split += ".000"
	return getStrWithFormat(time, split)
}

func getStrWithFormat(time time.Time, format string) string {
	return time.Format(format)
}

func getStrByTimeWithSplit(dateSpilt, timeSpilt interface{}) string {
	hasDate := dateSpilt != nil
	hasTime := timeSpilt != nil
	standDateTimeTemplateArr := strings.Split(standDateTimeTemplate, SPACE)
	result := EMPTY
	if hasDate {
		result += strings.ReplaceAll(standDateTimeTemplateArr[0], "%s", dateSpilt.(string))
	}
	if hasTime {
		if hasDate {
			result += SPACE
		}
		result += strings.ReplaceAll(standDateTimeTemplateArr[1], "%s", timeSpilt.(string))
	}
	if result == EMPTY {
		return getStrByTimeWithSplit(DASH, COLON)
	}
	return result
}


func isValid(str string) (error, []string, int){
	if str == EMPTY {
		return  nil, nil, 0
	}
	dateTimeStr := strings.Split(str, SPACE)
	total := len(dateTimeStr)
	if total == 2 {
		dateLen := len(dateTimeStr[0])
		if dateLen & 1 != 0 {
			return errors.New("invalid date str:" + dateTimeStr[0]), nil, 0
		}
		timeLen := len(dateTimeStr[1])
		if timeLen & 1 != 0 {
			return errors.New("invalid date str:" + dateTimeStr[1]), nil, 0
		}
	} else {
		// 年月 月日 时分 分秒
		partLen := len(str)
		if (partLen & 1) != 0 && partLen != 5{
			return errors.New("invalid date str:" + str), nil, 0
		}
	}
	return nil, dateTimeStr, total

}
/**
 * 根据日期字符串转time
 * tip:该方法效率高于<code> GetTimeByStrWithFormat </code> 推荐使用
 */
func GetTimeWithStr(str string, dateSplit, timeSpilt interface{}) (dateTime time.Time, err error){
	err, _, _ = isValid(str)
	if nil != err{
		return time.Time{}, err
	}
	split := getStrByTimeWithSplit(dateSplit, timeSpilt)
	dateTime, err = time.ParseInLocation(split, str, time.Local)
	return
}

func GetTimeByStrWithFormat(str string) (dateTime time.Time, err error){
	deferException()
	err, dateTimeStr, length := isValid(str)
	if nil != err {
		return time.Time{}, err
	}
	var timeSplit, dateSplit interface{}
	format := ""
	// 尝试解析前四位,如果能解析成功 则为年月日 否则为时分秒
	predictYear := str[2:3]
	_, err = strconv.ParseInt(predictYear, 10, 0)
	if nil != err {
		dateSplit = nil
		timeSplit = predictYear
	} else {
		dateSplit = str[4:5]
		if 1 == length {
			timeSplit = nil
		} else {
			timeSplit = dateTimeStr[1][2:3]
		}
	}
	// 解析遇到异常统一处理
	format = getStrByTimeWithSplit(dateSplit, timeSplit)
	location, _ := time.LoadLocation("Asia/ShangHai")
	dateTime, err = time.ParseInLocation(format, str,location )
	return
}

func hh()  {
	deferException()
	a := 1
	b := 0
	fmt.Println(a / b)
}

func deferException() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("catch exception:", err)
		}
	}()
}

// 测试
func main() {
	// time 转任意格式时间
	fmt.Println(GetStrByTime(time.Now()))
	fmt.Println(GetStrByTimeWithFormat(time.Now(), "#", nil))
	// 任意格式时间 转 time

	str, err := GetTimeWithStr("2023/03/21 13\\09\\44", "/", "\\")
	fmt.Println(str, err)
	// 任意格式
	format1, err := GetTimeByStrWithFormat("2023:03:21 22/33/03")
	fmt.Println(format1, err)
	format3, err := GetTimeByStrWithFormat("22/33/03")
	fmt.Println(format3, err)

	format4, err := GetTimeByStrWithFormat("2023:03:21")
	fmt.Println(format4, err)
	// 合法性验证 + 友好性提示
	format2, err := GetTimeByStrWithFormat("2023:03:21 22;33;3")
	fmt.Println(format2, err)




	2023-03-21 19:28:09
	2023#03#21
	2023-03-21 13:09:44 +0800 CST <nil>
	2023-03-21 22:33:03 +0800 CST <nil>
	0000-01-01 22:33:03 +0805 LMT <nil>
	2023-03-21 00:00:00 +0800 CST <nil>
	0001-01-01 00:00:00 +0000 UTC invalid date str:22;33;3
	
}


刚结束GO还有很多不熟悉,如果读者有更简便的方法,也欢迎评论分享,后续GO自研的工具会迁移到git,敬请关注。

曲终人不散~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值