Passed
Push — master ( 3df1d0...111a66 )
by Serhii
02:56 queued 01:25
created

timeago.calculateTheResult   C

Complexity

Conditions 11

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

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

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
	"fmt"
5
	"log"
6
	"math"
7
	"path"
8
	"runtime"
9
	"strconv"
10
	"strings"
11
	"time"
12
13
	"github.com/SerhiiCho/timeago/models"
14
	"github.com/SerhiiCho/timeago/utils"
15
)
16
17
// Take coverts given datetime into `x time ago` format.
18
// For displaying `Online` word if date interval within
19
// 60 seconds, add `|online` flag to the datetime string.
20
// Format must be [year-month-day hours:minutes:seconds}
21
func Take(datetime string) string {
22
	option, hasOption := getOption(&datetime)
23
24
	loc, _ := time.LoadLocation(location)
25
	parsedTime, _ := time.ParseInLocation("2006-01-02 15:04:05", datetime, loc)
26
	seconds := int(time.Now().In(loc).Sub(parsedTime).Seconds())
27
28
	switch {
29
	case seconds < 60 && option == "online":
30
		return trans().Online
31
	case seconds < 0:
32
		return getWords("seconds", 0)
33
	}
34
35
	return calculateTheResult(seconds, hasOption, option)
36
}
37
38
func calculateTheResult(seconds int, hasOption bool, option string) string {
39
	minutes, hours, days, weeks, months, years := getTimeCalculations(float64(seconds))
40
41
	switch {
42
	case hasOption && option == "online" && seconds < 60:
43
		return trans().Online
44
	case seconds < 60:
45
		return getWords("seconds", seconds)
46
	case minutes < 60:
47
		return getWords("minutes", minutes)
48
	case hours < 24:
49
		return getWords("hours", hours)
50
	case days < 7:
51
		return getWords("days", days)
52
	case weeks < 4:
53
		return getWords("weeks", weeks)
54
	case months < 12:
55
		if months == 0 {
56
			months = 1
57
		}
58
59
		return getWords("months", months)
60
	}
61
62
	return getWords("years", years)
63
}
64
65
func getTimeCalculations(seconds float64) (int, int, int, int, int, int) {
66
	minutes := math.Round(seconds / 60)
67
	hours := math.Round(seconds / 3600)
68
	days := math.Round(seconds / 86400)
69
	weeks := math.Round(seconds / 604800)
70
	months := math.Round(seconds / 2629440)
71
	years := math.Round(seconds / 31553280)
72
73
	return int(minutes), int(hours), int(days), int(weeks), int(months), int(years)
74
}
75
76
// get the last number of a given integer
77
func getLastNumber(num int) int {
78 1
	numStr := strconv.Itoa(num)
79 1
	result, _ := strconv.Atoi(numStr[len(numStr)-1:])
80
81 1
	return result
82
}
83
84
// getWords decides rather the word must be singular or plural,
85
// and depending on the result it adds the correct word after
86
// the time number
87
func getWords(timeKind string, num int) string {
88 1
	form := getLanguageForm(num)
89 1
	time := getTimeTranslations()
90
91 1
	translation := time[timeKind][form]
92
93 1
	return strconv.Itoa(num) + " " + translation + " " + trans().Ago
94
}
95
96
// getOption check if datetime has option with time,
97
// if yes, it will return this option and remove it
98
// from datetime
99
func getOption(datetime *string) (string, bool) {
100 1
	date := *datetime
101 1
	spittedDateString := strings.Split(date, "|")
102
103 1
	if len(spittedDateString) > 1 {
104 1
		*datetime = spittedDateString[0]
105 1
		return spittedDateString[1], true
106
	}
107
108 1
	return "", false
109
}
110
111
func trans() models.Lang {
112 1
	_, filename, _, ok := runtime.Caller(0)
113
114 1
	if !ok {
115
		panic("No caller information")
116
	}
117
118 1
	rootPath := path.Dir(filename)
119
120 1
	filePath := fmt.Sprintf(rootPath+"/langs/%s.json", language)
121
122 1
	thereIsFile, err := utils.FileExists(filePath)
123
124 1
	if !thereIsFile {
125
		log.Fatalf("File with the path: %s, doesn't exist", filePath)
126
	}
127
128 1
	if err != nil {
129
		log.Fatalf("Error while trying to read file %s. Error: %v", filePath, err)
130
	}
131
132 1
	return parseNeededFile(filePath)
133
}
134