-
Notifications
You must be signed in to change notification settings - Fork 0
/
dint.go
168 lines (139 loc) · 5.29 KB
/
dint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package dint
import (
"math"
"time"
)
// Dint Handling dates in a human-readable integer format (dint).
// Example: 20230912 = September 12, 2023
type Dint struct {
}
// Create Creates a dint using given year, month and day.
func (dint Dint) Create(year, month, day int) int {
return year*10000 + month*100 + day
}
// CreateFromTime Creates a dint from time.Time.
func (dint Dint) CreateFromTime(date time.Time) int {
return dint.Create(date.Year(), int(date.Month()), date.Day())
}
// Compose Composes a dint using any number of years, months and days.
func (dint Dint) Compose(year, month, day int) int {
return dint.AddDays(
dint.AddMonths(year*10000, month),
day)
}
// Year Returns the year of a given dint.
func (dint Dint) Year(year int) int {
return year / 10000
}
// Month Returns the month of a given dint.
func (dint Dint) Month(month int) int {
return month / 100 % 100
}
// Day Returns the day of the month of a given dint.
func (dint Dint) Day(day int) int {
return day % 100
}
// ToDate Creates a time.Time instance from a given dint.
func (dint Dint) ToDate(param int) time.Time {
return time.Date(dint.Year(param), time.Month(dint.Month(param)), dint.Day(param), 0, 0, 0, 0, time.UTC)
}
// Today Returns the current date dint.
func (dint Dint) Today() int {
return dint.CreateFromTime(time.Now())
}
// FirstDayOfMonth Returns a dint at the first day of a month of a given dint.
func (dint Dint) FirstDayOfMonth(param int) int {
return dint.Create(dint.Year(param), dint.Month(param), 1)
}
// LastDayOfMonth Returns a dint at the last day of a month of a given dint.
func (dint Dint) LastDayOfMonth(param int) int {
year, month := dint.Year(param), dint.Month(param)
return dint.Create(year, month, dint.DaysInAMonth(year, month))
}
// LaysInAMonth Returns the number of days in a given month.
func (dint Dint) LaysInAMonth(year, month int) int {
if month == 2 {
if dint.IsLeapYear(year) {
return 29
}
return 28
}
return 31 - ((month - 1) % 7 % 2)
}
// DaysInAMonth Returns the number of days in a given month.
func (dint Dint) DaysInAMonth(year, month int) int {
if month == 2 {
if dint.IsLeapYear(year) {
return 29
}
return 28
}
return 31 - ((month - 1) % 7 % 2)
}
// IsLeapYear Returns if a given year is a leap year.
func (dint Dint) IsLeapYear(year int) bool {
return !((year%4 != 0) || ((year%100 == 0) && (year%400 != 0)))
}
// Diff Returns the amount of days between two given dints.
func (dint Dint) Diff(dint1, dint2 int) int {
return dint.ToJulianDay(dint1) - dint.ToJulianDay(dint2)
}
// AddYears Adds years to a dint. A negative number is allowed.
// The resulting dint's number of days will be limited by the number of days in the resulting month.
func (dint Dint) AddYears(param int, years int) int {
return dint.ComposeLimit(param, dint.Year(param)+years, dint.Month(param))
}
// AddYearsExtend Adds years to a dint. A negative number is allowed.
// If the dint day is the last day in a month then the resulting day will be the last day in a month as well.
func (dint Dint) AddYearsExtend(param int, years int) int {
return dint.ComposeExtend(param, dint.Year(param)+years, dint.Month(param))
}
// AddMonths Adds months to a given dint. A negative number is allowed.
// The resulting dint's number of days will be limited by the number of days in the resulting month.
func (dint Dint) AddMonths(param int, months int) int {
monthsTotal := dint.Year(param)*12 + dint.Month(param) - 1 + months
return dint.ComposeLimit(param, monthsTotal/12, monthsTotal%12+1)
}
// AddMonthsExtend Adds months to a given dint. A negative number is allowed.
// If the dint day is the last day in a month then the resulting day will be the last day in a month as well.
func (dint Dint) AddMonthsExtend(param int, months int) int {
monthsTotal := dint.Year(param)*12 + dint.Month(param) - 1 + months
return dint.ComposeExtend(param, monthsTotal/12, monthsTotal%12+1)
}
// AddDays Adds a given number of days to a given dint. A negative number is allowed.
func (dint Dint) AddDays(param int, days int) int {
return dint.FromJulianDay(dint.ToJulianDay(param) + days)
}
// ComposeLimit Composes a dint with limited day based on the given year and month.
func (dint Dint) ComposeLimit(param int, year, month int) int {
return dint.Create(year, month, int(math.Min(float64(dint.Day(param)), float64(dint.DaysInAMonth(year, month)))))
}
// ComposeExtend Composes a dint with extended day based on the given year and month.
func (dint Dint) ComposeExtend(param int, year, month int) int {
if dint.DaysInAMonth(dint.Year(param), dint.Month(param)) == dint.Day(param) {
return dint.Create(year, month, dint.DaysInAMonth(year, month))
}
return dint.ComposeLimit(param, year, month)
}
// ToJulianDay Converts a dint to Julian Day.
func (dint Dint) ToJulianDay(param int) int {
year, month, day := dint.Year(param), dint.Month(param), dint.Day(param)
a := (14 - month) / 12
y := year + 4800 - a
m := month + 12*a - 3
return day + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 - 32045
}
// FromJulianDay Converts Julian Day to a dint.
func (dint Dint) FromJulianDay(julianDay int) int {
p := julianDay + 68569
q := 4 * p / 146097
r := p - (146097*q+3)/4
s := 4000 * (r + 1) / 1461001
t := r - 1461*s/4 + 31
u := 80 * t / 2447
v := u / 11
Y := 100*(q-49) + s + v
M := u + 2 - 12*v
D := t - 2447*u/80
return dint.Create(Y, M, D)
}