Passed
Push — master ( 2443e9...298cb8 )
by Serhii
02:08
created

timeago.calculateTheResult   C

Complexity

Conditions 11

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 11.0699

Importance

Changes 0
Metric Value
cc 11
eloc 20
nop 3
dl 0
loc 25
ccs 11
cts 12
cp 0.9167
crap 11.0699
rs 5.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like timeago.calculateTheResult often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package timeago
2
3
import (
4
	"strconv"
5
	"strings"
6
	"time"
7
)
8
9
// Take coverts given datetime into `x time ago` format.
10
// For displaying `Online` word if date interval within
11
// 60 seconds, add `|online` flag to the datetime string.
12
// Format must be [year-month-day hours:minutes:seconds}
13
func Take(datetime string) string {
14 1
	option, hasOption := getOption(&datetime)
15
16 1
	loc, _ := time.LoadLocation(location)
17 1
	parsedTime, _ := time.ParseInLocation("2006-01-02 15:04:05", datetime, loc)
18 1
	seconds := int(time.Now().In(loc).Sub(parsedTime).Seconds())
19
20 1
	switch {
21
	case seconds < 0 && option == "online":
22 1
		return trans("online")
23
	case seconds < 0:
24 1
		return getWords("seconds", 0)
25
	}
26
27 1
	return calculateTheResult(seconds, hasOption, option)
28
}
29
30
func calculateTheResult(seconds int, hasOption bool, option string) string {
31 1
	minutes, hours, days, weeks, months, years := getTimeCalculations(seconds)
32
33 1
	switch {
34
	case hasOption && option == "online" && seconds < 60:
35 1
		return trans("online")
36
	case seconds < 60:
37 1
		return getWords("seconds", seconds)
38
	case minutes < 60:
39 1
		return getWords("minutes", minutes)
40
	case hours < 24:
41 1
		return getWords("hours", hours)
42
	case days < 7:
43 1
		return getWords("days", days)
44
	case weeks < 4:
45 1
		return getWords("weeks", weeks)
46
	case months < 12:
47 1
		if months == 0 {
48
			months = 1
49
		}
50
51 1
		return getWords("months", months)
52
	}
53
54 1
	return getWords("years", years)
55
}
56
57
func getTimeCalculations(seconds int) (int, int, int, int, int, int) {
58 1
	minutes := seconds / 60
59 1
	hours := seconds / 3600
60 1
	days := seconds / 86400
61 1
	weeks := seconds / 604800
62 1
	months := seconds / 2629440
63 1
	years := seconds / 31553280
64
65 1
	return minutes, hours, days, weeks, months, years
66
}
67
68
// get the last number of a given integer
69
func getLastNumber(num int) int {
70 1
	numStr := strconv.Itoa(num)
71 1
	result, _ := strconv.Atoi(numStr[len(numStr)-1:])
72
73 1
	return result
74
}
75
76
// getWords decides rather the word must be singular or plural,
77
// and depending on the result it adds the correct word after
78
// the time number
79
func getWords(timeKind string, num int) string {
80 1
	lastNum := getLastNumber(num)
81 1
	index := 2
82
83 1
	switch {
84
	case lastNum == 1 && num == 11:
85 1
		index = 2
86
	case lastNum == 1 && language == "ru" || num == 1 && language == "en":
87 1
		index = 0
88
	case lastNum > 1 && lastNum < 5:
89 1
		index = 1
90
	}
91
92 1
	timeTrans := getTimeTranslations()
93
94 1
	return strconv.Itoa(num) + " " + timeTrans[timeKind][index] + " " + trans("ago")
95
}
96
97
// getTimeTranslations returns array of translations for different
98
// cases. For example `1 second` must not have `s` at the end
99
// but `2 seconds` requires `s`. So this method keeps all
100
// possible options for the translated word.
101
func getTimeTranslations() map[string][]string {
102 1
	return map[string][]string{
103
		"seconds": {trans("second"), trans("seconds"), trans("seconds2")},
104
		"minutes": {trans("minute"), trans("minutes"), trans("minutes2")},
105
		"hours":   {trans("hour"), trans("hours"), trans("hours2")},
106
		"days":    {trans("day"), trans("days"), trans("days2")},
107
		"weeks":   {trans("week"), trans("weeks"), trans("weeks2")},
108
		"months":  {trans("month"), trans("months"), trans("months2")},
109
		"years":   {trans("year"), trans("years"), trans("years2")},
110
	}
111
}
112
113
// getOption check if datetime has option with time,
114
// if yes, it will return this option and remove it
115
// from datetime
116
func getOption(datetime *string) (string, bool) {
117 1
	date := *datetime
118 1
	spittedDateString := strings.Split(date, "|")
119
120 1
	if len(spittedDateString) > 1 {
121 1
		*datetime = spittedDateString[0]
122 1
		return spittedDateString[1], true
123
	}
124
125 1
	return "", false
126
}
127
128
func trans(key string) string {
129 1
	if language == "ru" {
130 1
		return getRussian()[key]
131
	}
132
133 1
	return getEnglish()[key]
134
}
135