Passed
Pull Request — master (#6)
by Serhii
02:04
created

timeago.trans   A

Complexity

Conditions 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.2098

Importance

Changes 0
Metric Value
cc 3
eloc 8
nop 0
dl 0
loc 14
ccs 5
cts 7
cp 0.7143
crap 3.2098
rs 10
c 0
b 0
f 0
1
package timeago
2
3
import (
4
	"fmt"
5
	"log"
6
	"math"
7
	"strconv"
8
	"strings"
9
	"time"
10
11
	"github.com/SerhiiCho/timeago/models"
12
	"github.com/SerhiiCho/timeago/utils"
13
)
14
15
// Take coverts given datetime into `x time ago` format.
16
// For displaying `Online` word if date interval within
17
// 60 seconds, add `|online` flag to the datetime string.
18
// Format must be [year-month-day hours:minutes:seconds}
19
func Take(datetime string) string {
20 1
	option, hasOption := getOption(&datetime)
21
22 1
	loc, _ := time.LoadLocation(location)
23 1
	parsedTime, _ := time.ParseInLocation("2006-01-02 15:04:05", datetime, loc)
24 1
	seconds := int(time.Now().In(loc).Sub(parsedTime).Seconds())
25
26 1
	switch {
27
	case seconds < 0 && option == "online":
28 1
		return trans().Online
29
	case seconds < 0:
30 1
		return getWords("seconds", 0)
31
	}
32
33 1
	return calculateTheResult(seconds, hasOption, option)
34
}
35
36
func calculateTheResult(seconds int, hasOption bool, option string) string {
37 1
	minutes, hours, days, weeks, months, years := getTimeCalculations(float64(seconds))
38
39 1
	switch {
40
	case hasOption && option == "online" && seconds < 60:
41 1
		return trans().Online
42
	case seconds < 60:
43 1
		return getWords("seconds", seconds)
44
	case minutes < 60:
45 1
		return getWords("minutes", minutes)
46
	case hours < 24:
47 1
		return getWords("hours", hours)
48
	case days < 7:
49 1
		return getWords("days", days)
50
	case weeks < 4:
51 1
		return getWords("weeks", weeks)
52
	case months < 12:
53 1
		if months == 0 {
54
			months = 1
55
		}
56
57 1
		return getWords("months", months)
58
	}
59
60 1
	return getWords("years", years)
61
}
62
63
func getTimeCalculations(seconds float64) (int, int, int, int, int, int) {
64 1
	minutes := math.Round(seconds / 60)
65 1
	hours := math.Round(seconds / 3600)
66 1
	days := math.Round(seconds / 86400)
67 1
	weeks := math.Round(seconds / 604800)
68 1
	months := math.Round(seconds / 2629440)
69 1
	years := math.Round(seconds / 31553280)
70
71 1
	return int(minutes), int(hours), int(days), int(weeks), int(months), int(years)
72
}
73
74
// get the last number of a given integer
75
func getLastNumber(num int) int {
76 1
	numStr := strconv.Itoa(num)
77 1
	result, _ := strconv.Atoi(numStr[len(numStr)-1:])
78
79 1
	return result
80
}
81
82
// getWords decides rather the word must be singular or plural,
83
// and depending on the result it adds the correct word after
84
// the time number
85
func getWords(timeKind string, num int) string {
86 1
	lastNum := getLastNumber(num)
87 1
	index := 2
88
89 1
	switch {
90
	case lastNum == 1 && num == 11:
91 1
		index = 2
92
	case lastNum == 1 && language == "ru" || num == 1 && language == "en":
93 1
		index = 0
94
	case lastNum > 1 && lastNum < 5:
95 1
		index = 1
96
	}
97
98 1
	timeTrans := getTimeTranslations()
99
100 1
	return strconv.Itoa(num) + " " + timeTrans[timeKind][index] + " " + trans().Ago
101
}
102
103
// getTimeTranslations returns array of translations for different
104
// cases. For example `1 second` must not have `s` at the end
105
// but `2 seconds` requires `s`. So this method keeps all
106
// possible options for the translated word.
107
func getTimeTranslations() map[string][]string {
108 1
	return map[string][]string{
109
		"seconds": {trans().Second, trans().Seconds, trans().Seconds2},
110
		"minutes": {trans().Minute, trans().Minutes, trans().Minutes2},
111
		"hours":   {trans().Hour, trans().Hours, trans().Hours2},
112
		"days":    {trans().Day, trans().Days, trans().Days2},
113
		"weeks":   {trans().Week, trans().Weeks, trans().Weeks2},
114
		"months":  {trans().Month, trans().Months, trans().Months2},
115
		"years":   {trans().Year, trans().Years, trans().Years2},
116
	}
117
}
118
119
// getOption check if datetime has option with time,
120
// if yes, it will return this option and remove it
121
// from datetime
122
func getOption(datetime *string) (string, bool) {
123 1
	date := *datetime
124 1
	spittedDateString := strings.Split(date, "|")
125
126 1
	if len(spittedDateString) > 1 {
127 1
		*datetime = spittedDateString[0]
128 1
		return spittedDateString[1], true
129
	}
130
131 1
	return "", false
132
}
133
134
func trans() models.Lang {
135 1
	filePath := fmt.Sprintf("./langs/%s.json", language)
136
137 1
	thereIsFile, err := utils.FileExists(filePath)
138
139 1
	if !thereIsFile {
140
		log.Fatalf("File with the path: %s, doesn't exist", filePath)
141
	}
142
143 1
	if err != nil {
144
		log.Fatalf("Error while trying to read file %s. Error: %v", filePath, err)
145
	}
146
147 1
	return parseNeededFile(filePath)
148
}
149