go时间日期与时区相关操作

~~~

package main

import (
    "errors"
    "time"
    "github.com/jinzhu/now"
)

const (
    BINano  = "2006-01-02 15:04:05.000000000"
    BIMicro = "2006-01-02 15:04:05.000000"
    BIMil   = "2006-01-02 15:04:05.000"
    BISec   = "2006-01-02 15:04:05"
    BICST   = "2006-01-02 15:04:05 +0800 CST"
    BIUTC   = "2006-01-02 15:04:05 +0000 UTC"
    BIDate  = "2006-01-02"
    BITime  = "15:04:05"
)

/** 时间-时间戳-时间字符串互相转换

- time: auto timezone associated | 时间必关联时区属性

- str<=>time时,loc或者format不改变时间展示值,仅改变时区或偏移 | timezone associated

- timestamp: means seconds/nanoseconds of currenttime since January 1, 1970 UTC.

*/

// 获取time默认值, 造一个错误
func getTimeDefault(loc *time.Location) time.Time {
    loc = getLocationDefault(loc)
    t, _ := time.ParseInLocation("2006-01-02 15:04:05", "", loc)
    return t
}

func getLocationDefault(loc *time.Location) *time.Location {
    if loc == nil {
        loc, _ = time.LoadLocation("Local")
    }
    return loc
}

/** timestamp <--> time

- 使用当前配置的时区包

*/
// Timestamp2Time 时间戳转时间
func Timestamp2Time(stamp int64, nsec int64) time.Time {

    return time.Unix(stamp, nsec)
}

// Timestamp2TimeNano 时间戳转时间,纳秒
func Timestamp2TimeNano(stamp int64) time.Time {

    return Timestamp2Time(0, stamp)
}

func Timestamp2TimeMil(stamp int64) time.Time {

    return Timestamp2Time(0, stamp*1e6)
}

func Timestamp2TimeSec(stamp int64) time.Time {

    return Timestamp2Time(stamp, 0)
}

// Time2Timestamp 时间转时间戳
func Time2Timestamp(t time.Time, nsec int64) int64 {
    if nsec >= 0 {
        return t.Unix()
    }
    return t.UnixNano()
}

func Time2TimestampSec(t time.Time) int64 {
    return Time2Timestamp(t, 0)
}

func Time2TimestampMil(t time.Time) int64 {
    return Time2TimestampNano(t) / 1e6
}

func Time2TimestampNano(t time.Time) int64 {
    return Time2Timestamp(t, -1)
}

/** Timestr <--> time

- time->timestr 直接使用time.Format

*/

// Timestr2TimeBasic 字符串转时间
func Timestr2TimeBasic(value string, resultFormat string, resultLoc *time.Location) (time.Time, error) {
    /**
    - params
        value:             转换内容字符串
        resultFormat:    结果时间格式
        resultLoc:        结果时区
    */
    resultLoc = getLocationDefault(resultLoc)
    useFormat := []string{ // 可能的转换格式
        BINano, BIMicro, BIMil, BISec, BICST, BIUTC, BIDate, BITime,
        time.RFC3339,
        time.RFC3339Nano,
    }
    var t time.Time
    for _, usef := range useFormat {
        tt, error := time.ParseInLocation(usef, value, resultLoc)
        t = tt
        if error != nil {
            continue
        }
        break
    }
    if t == getTimeDefault(resultLoc) {
        return t, errors.New("时间字符串格式错误")
    }

    if resultFormat == "" {
        resultFormat = "2006-01-02 15:04:05"
    }
    st := t.Format(resultFormat)
    fixedt, _ := time.ParseInLocation(resultFormat, st, resultLoc)

    return fixedt, nil
}

func Timestr2Time(str string) (time.Time, error) {
    return Timestr2TimeBasic(str, "", nil)
}

/** Timestr <--> timestamp

- 先转换成时间,再转换时间戳

*/
// Timestr2TimestampBasic 时间字符串转时间戳, 单位秒
func Timestr2TimestampBasic(str string, format string, loc *time.Location) (float64, error) {
    t, err := Timestr2TimeBasic(str, format, loc)
    if err != nil {
        return -1., err
    }
    return (float64(t.UnixNano()) * 1.0) / 1e9, nil
}

// Timestr2TimestampWithFormat
func Timestr2TimestampWithFormat(str string, format string) (float64, error) {
    return Timestr2TimestampBasic(str, format, nil)
}

// Timestr2Timestamp 时间字符串转时间戳
func Timestr2Timestamp(str string) (float64, error) {
    return Timestr2TimestampBasic(str, "", nil)
}

/** Time <--> time

 */

// Time2TimeBasic 特定格式化的时
func Time2TimeBasic(t time.Time, format string, loc *time.Location) (time.Time, error) {
    loc = getLocationDefault(loc)
    if format == "" {
        return t, nil
    }
    strT := t.Format(format)

    resT, err := Timestr2TimeBasic(strT, format, loc)
    if err != nil {
        return t, err
    }
    return resT, nil

    // tmp := t.In(loc)
    // resT, errr := time.ParseInLocation(tmp.Format(format), format, loc)
    // if err != nil {
    //     return t, err
    // }
    // return resT, nil
}

// Time2Time 特定格式化的时间
func Time2Time(t time.Time, format string) (time.Time, error) {

    return Time2TimeBasic(t, format, nil)
}

/** 时间计算

 */

// TimePlus 时间加减
func TimePlus(t time.Time, value string) time.Time {
    // next 增加"[x]d"(天数)格式支持
    m, _ := time.ParseDuration(value)
    tCal := t.Add(m)
    return tCal
}

func TimeSubtraction(t1 time.Time, t2 time.Time) time.Duration {

    return t1.Sub(t2)
}

func TimeSubtractionDay(t1 time.Time, t2 time.Time) int64 {

    timeD := TimeSubtraction(t1, t2)
    return (int64)(timeD/time.Second) / 86400
}

func TimeStrSubtraction(str1 string, str2 string) time.Duration {

    t1, _ := Timestr2Time(str1)
    t2, _ := Timestr2Time(str2)

    return TimeSubtraction(t1, t2)
}

func TimeStrSubtractionDay(str1 string, str2 string) int64 {

    t1, _ := Timestr2Time(str1)
    t2, _ := Timestr2Time(str2)

    return TimeSubtractionDay(t1, t2)
}

// AddDate 增加年份 月份
func AddDate(t time.Time, years int, months int) time.Time {
    year, month, day := t.Date()
    hour, min, sec := t.Clock()

    // firstDayOfMonthAfterAddDate: years 年,months 月后的 那个月份的1号
    firstDayOfMonthAfterAddDate := time.Date(year+years, month+time.Month(months), 1,
        hour, min, sec, t.Nanosecond(), t.Location())
    // firstDayOfMonthAfterAddDate 月份的最后一天
    lastDay := now.New(firstDayOfMonthAfterAddDate).EndOfMonth().Day()

    // 如果 t 的天 > lastDay,则设置为lastDay
    // 如:t 为 2020-03-31 12:00:00 +0800,增加1个月,为4月31号
    // 但是4月没有31号,则设置为4月最后一天lastDay(30号)
    if day > lastDay {
        day = lastDay
    }

    return time.Date(year+years, month+time.Month(months), day,
        hour, min, sec, t.Nanosecond(), t.Location())
}

~~~

上一篇:Pandas系列教程(3)Pandas数据查询


下一篇:oracle笔记