Skip to content

Commit

Permalink
feat: first commit
Browse files Browse the repository at this point in the history
Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
  • Loading branch information
caarlos0 committed Aug 14, 2021
0 parents commit 1f3155e
Show file tree
Hide file tree
Showing 9 changed files with 400 additions and 0 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: build

on:
push:
branches:
- 'master'
tags:
- 'v*'
pull_request:

jobs:
build:
strategy:
matrix:
go-version: [ ~1.16 ]
os: [ ubuntu-latest, macos-latest, windows-latest ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Cache Go modules
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: CI
run: make setup ci
- name: Upload coverage
uses: codecov/codecov-action@v2
if: matrix.os == 'ubuntu-latest'
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.txt
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
if: success() && startsWith(github.ref, 'refs/tags/') && matrix.os == 'ubuntu-latest'
with:
version: latest
distribution: goreleaser-pro
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }}
TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }}
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
22 changes: 22 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: golangci-lint
on:
push:
tags:
- v*
branches:
- master
- main
pull_request:
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v2
with:
go-version: ~1.16
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
skip-go-installation: true
8 changes: 8 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
linters:
enable:
- thelper
- gofumpt
- tparallel
- unconvert
- unparam
- wastedassign
3 changes: 3 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
includes:
- from_url:
url: https://raw.githubusercontent.com/caarlos0/.goreleaserfiles/main/lib.yml
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# timea.go
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/caarlos0/timea.go

go 1.16

require github.com/matryer/is v1.4.0 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
193 changes: 193 additions & 0 deletions timea.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Package timeago provides a simple library to format a time in a "time ago" manner.
package timeago

import (
"fmt"
"reflect"
"time"
)

// Precision define the minimun amount of time to be considered.
type Precision uint

const (
// SecondPrecision is the second precision.
SecondPrecision Precision = iota

// MinutePrecision is the minute precision.
MinutePrecision

// HourPrecision is the hour precision.
HourPrecision

// DayPrecision is the day precision.
DayPrecision

// MonthPrecision is the month precision.
MonthPrecision

// YearPrecision is the year precision.
YearPrecision
)

// Options define the options of the library.
type Options struct {
Precision Precision
Format Format
}

// Of returns the string representation of the given time with the given options.
func Of(t time.Time, options ...Options) string {
opt := Options{
Precision: SecondPrecision,
Format: DefaultFormat,
}

for _, o := range options {
if o.Precision != 0 {
opt.Precision = o.Precision
}
if !reflect.DeepEqual(o.Format, Format{}) {
opt.Format = o.Format
}
}

switch opt.Precision {
case SecondPrecision:
seconds := time.Since(t).Round(time.Second).Seconds()
if seconds == 0 {
return opt.Format.ThisSecond
}
if seconds == 1 {
return opt.Format.LastSecond
}
if seconds < 60 {
return fmt.Sprintf(opt.Format.SecondsAgo, int(seconds))
}
return Of(t, Options{
Precision: MinutePrecision,
})
case MinutePrecision:
minutes := time.Since(t).Round(time.Minute).Minutes()
if minutes == 0 {
return opt.Format.ThisMinute
}
if minutes == 1 {
return opt.Format.LastMinute
}
if minutes < 60 {
return fmt.Sprintf(opt.Format.MinutesAgo, int(minutes))
}
return Of(t, Options{
Precision: HourPrecision,
})
case HourPrecision:
hours := time.Since(t).Round(time.Hour).Hours()
if hours == 0 {
return opt.Format.ThisHour
}
if hours == 1 {
return opt.Format.LastHour
}
if hours < 24 {
return fmt.Sprintf(opt.Format.HoursAgo, int(hours))
}
return Of(t, Options{
Precision: DayPrecision,
})
case DayPrecision:
days := time.Since(t).Round(time.Hour*24).Hours() / 24
if days == 0 {
return opt.Format.Today
}
if days == 1 {
return opt.Format.Yesterday
}
if days < 30 {
return fmt.Sprintf(opt.Format.DaysAgo, int(days))
}
return Of(t, Options{
Precision: MonthPrecision,
})
case MonthPrecision:
months := time.Since(t).Round(time.Hour*24*30).Hours() / (24 * 30)
if months == 0 {
return opt.Format.ThisMonth
}
if months == 1 {
return opt.Format.LastMonth
}
if months < 12 {
return fmt.Sprintf(opt.Format.MonthsAgo, int(months))
}
return Of(t, Options{
Precision: YearPrecision,
})
case YearPrecision:
years := time.Since(t).Round(time.Hour*24*365).Hours() / (24 * 365)
if years == 0 {
return opt.Format.ThisYear
}
if years == 1 {
return opt.Format.LastYear
}
return fmt.Sprintf(opt.Format.YearsAgo, int(years))
}

// this should never happen
return t.String()
}

// Format is the format of the string returned by the library.
type Format struct {
ThisSecond string
LastSecond string
SecondsAgo string

ThisMinute string
LastMinute string
MinutesAgo string

ThisHour string
LastHour string
HoursAgo string

Today string
Yesterday string
DaysAgo string

ThisMonth string
LastMonth string
MonthsAgo string

ThisYear string
LastYear string
YearsAgo string
}

// DefaultFormat is the default format of the string returned by the library.
var DefaultFormat = Format{
ThisSecond: "now",
LastSecond: "1 second ago",
SecondsAgo: "%d seconds ago",

ThisMinute: "now",
LastMinute: "1 minute ago",
MinutesAgo: "%d minutes ago",

ThisHour: "this hour",
LastHour: "last hour",
HoursAgo: "%d hours ago",

Today: "today",
Yesterday: "yesterday",
DaysAgo: "%d days ago",

ThisMonth: "this month",
LastMonth: "last month",
MonthsAgo: "%d months ago",

ThisYear: "this year",
LastYear: "last year",
YearsAgo: "%d years ago",
}
Loading

0 comments on commit 1f3155e

Please sign in to comment.