Skip to content

Commit

Permalink
...copy
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangliang committed Apr 25, 2023
0 parents commit ef38130
Show file tree
Hide file tree
Showing 8 changed files with 438 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
18 changes: 18 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
language: go

go:
- 1.9
- "1.10"
- 1.11
- 1.12

install:
- go get github.com/mattn/goveralls

script:
- go test -v -covermode=count -coverprofile=coverage.out
- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN

env:
global:
secure: "RKp8cn1fCYU6PM4V7CUzW7R0T79e8MAwLpLV/NjjLKzckFnI2DT5Td1s2hdiYaqncN/PbIl/SHMt6CJadEJOFZqiagc8blywnsPMp8ABpAIMQS3Ae7ZeQoPDotuP5pPMmmCryVqWH75XzmsicNFDXbd6z+9dWyoSVHIfxrOOmmrmsMzdg/MFiM8EDFe0xrgJQIuyjzhR34dtTHgbvzNaixBivIIIU3w0LAietuagQjWA7sNNfwFTOVl97usiLJfiSxIta6rvV6oFcpxe3YuGwlSbNEeaJoeLC564nGrJFcLmrUs0M6ZYQ1uOAoADiWSv/t3K1pdQRO51VbEl3LveEOQyPV3p06TKVhvdC9aZz2KJqM6DdrJ/rkU5zUCYtv75dbT31QU3FW0rcdQjoMdWp/m/Llyv0KaUPk7JNOwfpCNPlrj0zQzk1/4dqQwmsJGL21kO+mABWWJamFOD1kJ/52DnJE3hbeZFnHMfsml14RZeDSDJnzlHjyIalPfC/koJpPuxu/9O7qxxjOJ5WSKRU9p1a5zmTD/9mUNOvVHOR0ohJa92DL8WPyVqoYJuFvgK+2QI/CboRYTXbyMFC7Tv0OGxjzDBlqUwsztHa43LsvvL0aONT69ogjUKrblNFcFNt+q368QE021cKw2D1yP6NpDcIVeCkkDfJ4dXMopl/o0="
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2019, Andrew Chang
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# timeconv

Package timeconv provides some simple function to convert go time.Time values.

[![GoDoc](https://godoc.org/github.com/Andrew-M-C/go.timeconv?status.svg)](https://godoc.org/github.com/Andrew-M-C/go.timeconv)
[![Build status](https://travis-ci.org/Andrew-M-C/go.timeconv.svg?branch=master)](https://travis-ci.org/Andrew-M-C/go.timeconv)
[![Coverage Status](https://coveralls.io/repos/github/Andrew-M-C/go.timeconv/badge.svg?branch=master)](https://coveralls.io/github/Andrew-M-C/go.timeconv?branch=master)
[![Latest](https://img.shields.io/badge/latest-v0.4.0-blue.svg)](https://github.com/Andrew-M-C/go.timeconv/tree/v0.4.0)

The function `AddDate` in [package time](https://golang.org/pkg/time/) adds dates passed in format of years, months and days. In the biginning, I thought it did handle different date of month. However, it is NOT.

For example, in many case in real life, if a month is added to 2019-01-31, the result should be 2019-01-28, identifying last day of the month. But the result with `AddDate` in package `time` will be 2019-03-03 ([Playground](https://play.golang.org/p/3eWrvAVzHUm))

This simple package `timeconv` provides a simple alternate of `AddDate` function, it focus on month operation and corrects result day for return. Please refer to the demo below for usage:

```go
package main

import (
"fmt"
"time"
"github.com/Andrew-M-C/go.timeconv"
)

func main() {
t := time.Date(2019, 1, 31, 0, 0, 0, 0, time.UTC)
nt := t.AddDate(0, 1, 0) // Add one month
fmt.Printf("%v\n", nt) // 2019-03-03 00:00:00 +0000 UTC, not expected

nt = timeconv.AddDate(t, 0, 1, 0)
fmt.Printf("%v\n", nt) // 2019-02-28 00:00:00 +0000 UTC
}
```

[Playground](https://play.golang.org/p/-2tnI8Ejxwh)

Additionally, there is a pointer version: `func AddDateP(t *time.Time, years, months, days int)`
21 changes: 21 additions & 0 deletions example_timeconv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package timeconv_test

import (
"fmt"

timeconv "github.com/Andrew-M-C/go.timeconv"
)

func Example() {
p := fmt.Println
t := timeconv.Date(2020, 1, 31)

p(t)
p(t.AddDate(0, 1, 0))
p(timeconv.AddDate(t, 0, 1, 0))

// Output:
// 2020-01-31 00:00:00 +0000 UTC
// 2020-03-02 00:00:00 +0000 UTC
// 2020-02-29 00:00:00 +0000 UTC
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/Andrew-M-C/go.timeconv

go 1.13
171 changes: 171 additions & 0 deletions timeconv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Package timeconv provides some simple function to convert go time.Time values. Please refer to functions below.
package timeconv

import (
// "log"
"bytes"
"fmt"
"time"
)

var (
uptime = time.Now()
)

// AddDate returns the time corresponding to adding the given number of years, months, and days to t. For example, AddDate(-1, 2, 3) applied to January 1, 2011 returns March 4, 2010.
//
// However, this version of AddDate will examine the date of month. For example, AddDate(0, 1, 0) applied to January 31, 2011 returns Feburary 28, 2011 instead of March 3, 2011.
func AddDate(t time.Time, years, months, days int) time.Time {
// limit month
if months >= 12 || months <= 12 {
years += months / 12
months = months % 12
}

// get datetime parts
ye := t.Year()
mo := t.Month()
da := t.Day()
hr := t.Hour()
mi := t.Minute()
se := t.Second()
ns := t.Nanosecond()
lo := t.Location()

// log.Printf("input: %d - %d - %d\n", ye, mo, da)
// log.Printf("delta: %d - %d - %d\n", years, months, days)

// years
ye += years

// months
mo += time.Month(months)
if mo > 12 {
mo -= 12
ye++
} else if mo < 1 {
mo += 12
ye--
}

// after adding month, we should adjust day of month value
if da <= 28 {
// nothing to change
} else if da == 29 {
if mo == 2 {
if !isLeapYear(ye) {
da = 28
}
}
// else, OK

} else if da == 30 {
if mo == 2 {
if isLeapYear(ye) {
da = 29
} else {
da = 28
}
}
// else, OK

} else if da == 31 {
switch mo {
case 2:
if isLeapYear(ye) {
da = 29
} else {
da = 28
}
case 1, 3, 5, 7, 8, 10, 12:
da = 31
case 4, 6, 9, 11:
da = 30
}
}

// date
da += days

// return
return time.Date(ye, mo, da, hr, mi, se, ns, lo)
}

func isLeapYear(year int) bool {
if year%4 == 0 {
if year%100 == 0 {
return year%400 == 0
}
return true
}
return false
}

// AddDateP is the pointer version of AddDate()
func AddDateP(t *time.Time, years, months, days int) {
*t = AddDate(*t, years, months, days)
}

// Date returns a time.Time value with year, month, day and location only. If not indecating loc, UTC will be used.
func Date(year int, month time.Month, day int, loc ...*time.Location) time.Time {
if len(loc) == 0 {
return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
}
return time.Date(year, month, day, 0, 0, 0, 0, loc[0])
}

// UnixMilli returns Unix timestamp in milliseconds
func UnixMilli(t time.Time) int64 {
return t.UnixNano() / int64(time.Millisecond)
}

// UnixMicro returns Unix timestamp in microseconds
func UnixMicro(t time.Time) int64 {
return t.UnixNano() / int64(time.Microsecond)
}

// ProcUpDuration returns a rough duration indecating how long current process has run.
func ProcUpDuration() time.Duration {
return time.Since(uptime)
}

// YYYYMMDD is equivalent to t.Format(fmt.Sprintf("2006%s01%s02", seperator, seperator))
func YYYYMMDD(t time.Time, seperator string) string {
f := fmt.Sprintf("2006%s01%s02", seperator, seperator)
return t.Format(f)
}

// YYMMDD is equivalent to t.Format(fmt.Sprintf("06%s01%s02", seperator, seperator))
func YYMMDD(t time.Time, seperator string) string {
f := fmt.Sprintf("06%s01%s02", seperator, seperator)
return t.Format(f)
}

// HHMM is equivalent to t.Format(fmt.Sprintf("03%s04", seperator))
func HHMM(t time.Time, seperator string) string {
f := fmt.Sprintf("03%s04", seperator)
return t.Format(f)
}

// HHMMSS is equivalent to t.Format(fmt.Sprintf("03%s04%s05", seperator, seperator)).
// With decimal, additional decimal digits of seconds will be added after a dot.
func HHMMSS(t time.Time, seperator string, decimal ...int) string {
buff := bytes.Buffer{}

buff.WriteString("03")
buff.WriteString(seperator)
buff.WriteString("04")
buff.WriteString(seperator)
buff.WriteString("05")

if len(decimal) > 0 && decimal[0] != 0 {
buff.WriteRune('.')
dec := decimal[0]

for i := 0; i < dec && i < 9; i++ {
buff.WriteRune('0')
}
}

return t.Format(buff.String())
}
Loading

0 comments on commit ef38130

Please sign in to comment.