Passed
Push — v3.0.0 ( 670783...5b9f70 )
by Serhii
01:17
created

timeago.parseStrIntoTime   A

Complexity

Conditions 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
dl 0
loc 13
rs 10
c 0
b 0
f 0
nop 1
1
package timeago
2
3
import (
4
	"fmt"
5
	"log"
6
	"math"
7
	"strconv"
8
	"strings"
9
	"time"
10
11
	"github.com/SerhiiCho/timeago/v3/config"
12
)
13
14
var (
15
	cachedJsonResults = map[string]*LangSet{}
16
	options           = []Option{}
17
	langSet           *LangSet
18
	conf              = config.New("en", "", []config.Translation{})
19
)
20
21
// Parse coverts given datetime into `x time ago` format.
22
// First argument can have 3 types:
23
// 1. int (Unix timestamp)
24
// 2. time.Time (Type from Go time package)
25
// 3. string (Datetime string in format 'YYYY-MM-DD HH:MM:SS')
26
func Parse(datetime interface{}, opts ...Option) string {
27
	options = []Option{}
28
	var input time.Time
29
30
	switch date := datetime.(type) {
31
	case int:
32
		input = parseTimestampIntoTime(date)
33
	case string:
34
		input = parseStrIntoTime(date)
35
	default:
36
		input = datetime.(time.Time)
37
	}
38
39
	enableOptions(opts)
40
41
	return calculateTimeAgo(input)
42
}
43
44
func Configure(c *config.Config) {
45
	if c.Language != "" {
46
		conf.Language = c.Language
47
	}
48
49
	if c.Location != "" {
50
		conf.Location = c.Location
51
	}
52
53
	if len(c.Translations) > 0 {
54
		conf.Translations = c.Translations
55
	}
56
}
57
58
func parseStrIntoTime(datetime string) time.Time {
59
	if !conf.LocationIsSet() {
60
		parsedTime, _ := time.Parse("2006-01-02 15:04:05", datetime)
61
		return parsedTime
62
	}
63
64
	parsedTime, err := time.ParseInLocation("2006-01-02 15:04:05", datetime, location())
65
66
	if err != nil {
67
		log.Fatalf("[Timeago]: ERROR: %v", err)
68
	}
69
70
	return parsedTime
71
}
72
73
func location() *time.Location {
74
	loc, err := time.LoadLocation(conf.Location)
75
76
	if err != nil {
77
		log.Fatalf("[Timeago]: ERROR: %v", err)
78
	}
79
80
	return loc
81
}
82
83
func calculateTimeAgo(t time.Time) string {
84
	now := time.Now()
85
86
	if conf.LocationIsSet() {
87
		t = applyLocationToTime(t)
88
		now = applyLocationToTime(now)
89
	}
90
91
	seconds := now.Sub(t).Seconds()
92
93
	if seconds < 0 {
94
		enableOption(Upcoming)
95
		seconds = math.Abs(seconds)
96
	}
97
98
	langSet = NewLangSet()
99
100
	switch {
101
	case seconds < 60 && optionIsEnabled("online"):
102
		return langSet.Online
103
	case seconds < 0:
104
		return getWords(langSet.Second, 0)
105
	}
106
107
	timeUnit := generateTimeUnit(int(seconds))
108
109
	return timeUnit
110
}
111
112
func generateTimeUnit(seconds int) string {
113
	minutes, hours, days, weeks, months, years := getTimeCalculations(float64(seconds))
114
115
	switch {
116
	case optionIsEnabled("online") && seconds < 60:
117
		return langSet.Online
118
	case optionIsEnabled("justNow") && seconds < 60:
119
		return langSet.JustNow
120
	case seconds < 60:
121
		return getWords(langSet.Second, seconds)
122
	case minutes < 60:
123
		return getWords(langSet.Minute, minutes)
124
	case hours < 24:
125
		return getWords(langSet.Hour, hours)
126
	case days < 7:
127
		return getWords(langSet.Day, days)
128
	case weeks < 4:
129
		return getWords(langSet.Week, weeks)
130
	case months < 12:
131
		if months == 0 {
132
			months = 1
133
		}
134
135
		return getWords(langSet.Month, months)
136
	}
137
138
	return getWords(langSet.Year, years)
139
}
140
141
// getWords decides rather the word must be singular or plural,
142
// and depending on the result it adds the correct word after
143
// the time number
144
func getWords(final LangForms, num int) string {
145
	form := identifyLocaleForm(num)
146
147
	result := langSet.Format
148
	result = strings.Replace(result, "{timeUnit}", final[form], -1)
149
	result = strings.Replace(result, "{num}", strconv.Itoa(num), -1)
150
151
	if optionIsEnabled("noSuffix") || optionIsEnabled("upcoming") {
152
		result = strings.Replace(result, "{ago}", "", -1)
153
		return strings.Trim(result, " ")
154
	}
155
156
	return strings.Replace(result, "{ago}", langSet.Ago, -1)
157
}
158
159
func identifyLocaleForm(num int) string {
160
	rule, err := identifyGrammarRules(num, conf.Language)
161
162
	if err != nil {
163
		fmt.Println(err)
164
		return "other"
165
	}
166
167
	switch {
168
	case rule.Zero:
169
		return "zero"
170
	case rule.One:
171
		return "one"
172
	case rule.Few:
173
		return "few"
174
	case rule.Two:
175
		return "two"
176
	case rule.Many:
177
		return "many"
178
	}
179
180
	return "other"
181
}
182
183
func applyLocationToTime(t time.Time) time.Time {
184
	return t.In(location())
185
}
186
187
func getTimeCalculations(seconds float64) (int, int, int, int, int, int) {
188
	minutes := math.Round(seconds / 60)
189
	hours := math.Round(seconds / 3600)
190
	days := math.Round(seconds / 86400)
191
	weeks := math.Round(seconds / 604800)
192
	months := math.Round(seconds / 2629440)
193
	years := math.Round(seconds / 31553280)
194
195
	return int(minutes), int(hours), int(days), int(weeks), int(months), int(years)
196
}
197