Compare commits
No commits in common. "cc6e52d352c233b2b507ab1c870717f4fe6f4149" and "da53b8c6b6888e46f2ae03dbc19b0851b449503d" have entirely different histories.
cc6e52d352
...
da53b8c6b6
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/ck
|
|
|
@ -27,10 +27,6 @@ var (
|
||||||
Background(tcell.ColorReset).
|
Background(tcell.ColorReset).
|
||||||
Foreground(tcell.GetColor("green")).
|
Foreground(tcell.GetColor("green")).
|
||||||
Bold(true)
|
Bold(true)
|
||||||
HolyStyle tcell.Style = tcell.StyleDefault.
|
|
||||||
Background(tcell.ColorReset).
|
|
||||||
Foreground(tcell.GetColor("red")).
|
|
||||||
Bold(true)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func centeredText(s string, x, y, width int, scr tcell.Screen, style tcell.Style) {
|
func centeredText(s string, x, y, width int, scr tcell.Screen, style tcell.Style) {
|
||||||
|
|
|
@ -169,7 +169,7 @@ func DrawWall() {
|
||||||
Wall.Clear()
|
Wall.Clear()
|
||||||
w, h := Wall.Size()
|
w, h := Wall.Size()
|
||||||
if w < maxMonthWidth+2*smallGap || h < maxMonthHeight+2*smallGap+titleHeight {
|
if w < maxMonthWidth+2*smallGap || h < maxMonthHeight+2*smallGap+titleHeight {
|
||||||
wrappedText("Екран је премали за календар.", Wall, DefStyle) // The screen is too small for the calender
|
wrappedText("Екран је премали за календар.", Wall, DefStyle)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
monthsWide = (w - 2*smallGap + largeGap) / (maxMonthWidth + largeGap)
|
monthsWide = (w - 2*smallGap + largeGap) / (maxMonthWidth + largeGap)
|
||||||
|
|
12
go.mod
12
go.mod
|
@ -1,15 +1,5 @@
|
||||||
module gitlab.com/tvrdosrz/ck
|
module gitlab.com/tvrdosrz/ck
|
||||||
|
|
||||||
go 1.22
|
go 1.16
|
||||||
|
|
||||||
require github.com/gdamore/tcell/v2 v2.3.11
|
require github.com/gdamore/tcell/v2 v2.3.11
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/gdamore/encoding v1.0.0 // indirect
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
|
|
||||||
github.com/mattn/go-runewidth v0.0.10 // indirect
|
|
||||||
github.com/rivo/uniseg v0.1.0 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
|
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
|
|
||||||
golang.org/x/text v0.3.0 // indirect
|
|
||||||
)
|
|
||||||
|
|
122
julian/julian.go
122
julian/julian.go
|
@ -1,122 +0,0 @@
|
||||||
package julian
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// TODO: describe how time doesn't go past BCE, and therefore we don't either
|
|
||||||
// Keep in mind, Go's time.Time gregorian dates are `proleptic`, ie. there is
|
|
||||||
// no need to give special care to dates before 15. October 1582.
|
|
||||||
type Date struct {
|
|
||||||
year int
|
|
||||||
month time.Month
|
|
||||||
day int
|
|
||||||
}
|
|
||||||
|
|
||||||
func greaterOrEqual(a, b Date) bool {
|
|
||||||
if a.year != b.year {
|
|
||||||
return a.year > b.year
|
|
||||||
} else if a.month != b.month {
|
|
||||||
return a.month > b.month
|
|
||||||
} else {
|
|
||||||
return a.day >= b.day
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func monthLength(year int, month time.Month) int {
|
|
||||||
lengths := map[time.Month]int{
|
|
||||||
time.January: 31,
|
|
||||||
time.March: 31,
|
|
||||||
time.April: 30,
|
|
||||||
time.May: 31,
|
|
||||||
time.June: 30,
|
|
||||||
time.July: 31,
|
|
||||||
time.August: 31,
|
|
||||||
time.September: 30,
|
|
||||||
time.October: 31,
|
|
||||||
time.November: 30,
|
|
||||||
time.December: 31,
|
|
||||||
}
|
|
||||||
if _, ok := lengths[month]; ok {
|
|
||||||
return lengths[month]
|
|
||||||
}
|
|
||||||
// February
|
|
||||||
if year%4 == 0 {
|
|
||||||
return 29
|
|
||||||
}
|
|
||||||
return 28
|
|
||||||
}
|
|
||||||
|
|
||||||
func dateDiff(d Date, days int) Date {
|
|
||||||
// keep in mind throughout this code that the original "days" value can
|
|
||||||
// be negative
|
|
||||||
var fourYearPeriods int
|
|
||||||
var periodLen int = (3 * 365) + 366
|
|
||||||
// a difference which is an exact multiple of 4 years can be dealt with
|
|
||||||
// easily, so we only have to take greater care with the remainder
|
|
||||||
fourYearPeriods, days = days/periodLen, days%periodLen
|
|
||||||
// this `if' will happen if days was originally <0, AND is not an exact
|
|
||||||
// multiple of periodLen
|
|
||||||
if days < 0 {
|
|
||||||
fourYearPeriods -= 1
|
|
||||||
days += periodLen
|
|
||||||
}
|
|
||||||
// now days must be 0 <= days < periodLen, so our job is easier
|
|
||||||
// first we shift in the big periods
|
|
||||||
d.year += fourYearPeriods * 4
|
|
||||||
|
|
||||||
// We shift the date to the first of the month to simplify our
|
|
||||||
// calculation
|
|
||||||
days += d.day - 1
|
|
||||||
d.day = 1
|
|
||||||
// since days < periodLen+31-1, we will go through this loop at most
|
|
||||||
// 4*12+1 = 49 times
|
|
||||||
for days >= monthLength(d.year, d.month) {
|
|
||||||
days -= monthLength(d.year, d.month)
|
|
||||||
d.year, d.month = nextMonth(d.year, d.month)
|
|
||||||
}
|
|
||||||
d.day += days
|
|
||||||
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextMonth(year int, month time.Month) (int, time.Month) {
|
|
||||||
if month == time.December {
|
|
||||||
return year + 1, time.January
|
|
||||||
} else {
|
|
||||||
return year, month + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(year int, month time.Month, day int) Date {
|
|
||||||
// TODO: deal with users giving negative dates
|
|
||||||
for day > monthLength(year, month) {
|
|
||||||
day -= monthLength(year, month)
|
|
||||||
year, month = nextMonth(year, month)
|
|
||||||
}
|
|
||||||
return Date{year, month, day}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The algorithm, in large part: follows this article:
|
|
||||||
// https://en.wikipedia.org/wiki/Conversion_between_Julian_and_Gregorian_calendars
|
|
||||||
func ToTime(d Date) time.Time {
|
|
||||||
offset := -2
|
|
||||||
borderDate := Date{100, time.March, 2}
|
|
||||||
// We don't increase the offset for years divisible by 400, ie. every
|
|
||||||
// fourth loop, we keep track of that with skipYear, we can't simply
|
|
||||||
// check borderDate.year % 400, because when we reach 31. December
|
|
||||||
// 8299, the year will not be divisible by 100 anymore
|
|
||||||
skipYear := 1
|
|
||||||
for greaterOrEqual(d, borderDate) {
|
|
||||||
// We can simply add 100 to the year because in the julian
|
|
||||||
// calendar, if a date exists in year y, it always exists in
|
|
||||||
// year y+100
|
|
||||||
borderDate.year += 100
|
|
||||||
if skipYear%4 != 0 {
|
|
||||||
borderDate = dateDiff(borderDate, -1)
|
|
||||||
offset++
|
|
||||||
}
|
|
||||||
skipYear++
|
|
||||||
}
|
|
||||||
|
|
||||||
d = dateDiff(d, offset)
|
|
||||||
return time.Date(d.year, d.month, d.day, 0, 0, 0, 0, time.UTC)
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
package julian
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMonthLength(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
y int
|
|
||||||
m time.Month
|
|
||||||
want int
|
|
||||||
}{
|
|
||||||
{2001, time.January, 31},
|
|
||||||
{2001, time.February, 28},
|
|
||||||
{2000, time.February, 29},
|
|
||||||
{2001, time.March, 31},
|
|
||||||
{2001, time.April, 30},
|
|
||||||
{2001, time.May, 31},
|
|
||||||
{2001, time.June, 30},
|
|
||||||
{2001, time.July, 31},
|
|
||||||
{2001, time.August, 31},
|
|
||||||
{2001, time.September, 30},
|
|
||||||
{2001, time.October, 31},
|
|
||||||
{2001, time.November, 30},
|
|
||||||
{2001, time.December, 31},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
testname := fmt.Sprintf("%v, %d", tt.m, tt.y)
|
|
||||||
t.Run(testname, func(t *testing.T) {
|
|
||||||
ans := monthLength(tt.y, tt.m)
|
|
||||||
if ans != tt.want {
|
|
||||||
t.Errorf("got %d, want %d", ans, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDateDiff(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
d Date
|
|
||||||
days int
|
|
||||||
want Date
|
|
||||||
}{
|
|
||||||
{Date{2001, time.January, 20}, 5, Date{2001, time.January, 25}},
|
|
||||||
{Date{2001, time.February, 28}, 5, Date{2001, time.March, 5}},
|
|
||||||
{Date{2004, time.February, 28}, 5, Date{2004, time.March, 4}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
testname := fmt.Sprintf("%v, %d", tt.d, tt.days)
|
|
||||||
t.Run(testname, func(t *testing.T) {
|
|
||||||
ans := dateDiff(tt.d, tt.days)
|
|
||||||
if ans != tt.want {
|
|
||||||
t.Errorf("got %d, want %d", ans, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextMonth(t *testing.T) {
|
|
||||||
ans1, ans2 := nextMonth(2000, time.December)
|
|
||||||
if ans1 != 2001 || ans2 != time.January {
|
|
||||||
t.Errorf("nextMonth(2000, time.December) = %d, %v; want 2001, time.January", ans1, ans2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToTime(t *testing.T) {
|
|
||||||
gDate := func(year int, month time.Month, day int) time.Time {
|
|
||||||
return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
|
|
||||||
}
|
|
||||||
var tests = []struct {
|
|
||||||
d Date
|
|
||||||
want time.Time
|
|
||||||
}{
|
|
||||||
{Date{100, time.February, 29}, gDate(100, time.February, 27)},
|
|
||||||
{Date{100, time.March, 1}, gDate(100, time.February, 28)},
|
|
||||||
{Date{100, time.March, 2}, gDate(100, time.March, 1)},
|
|
||||||
{Date{200, time.February, 28}, gDate(200, time.February, 27)},
|
|
||||||
{Date{200, time.February, 29}, gDate(200, time.February, 28)},
|
|
||||||
{Date{200, time.March, 1}, gDate(200, time.March, 1)},
|
|
||||||
{Date{300, time.February, 28}, gDate(300, time.February, 28)},
|
|
||||||
{Date{300, time.February, 29}, gDate(300, time.March, 1)},
|
|
||||||
{Date{300, time.March, 1}, gDate(300, time.March, 2)},
|
|
||||||
{Date{500, time.February, 28}, gDate(500, time.March, 1)},
|
|
||||||
{Date{500, time.February, 29}, gDate(500, time.March, 2)},
|
|
||||||
{Date{500, time.March, 1}, gDate(500, time.March, 3)},
|
|
||||||
{Date{600, time.February, 28}, gDate(600, time.March, 2)},
|
|
||||||
{Date{600, time.February, 29}, gDate(600, time.March, 3)},
|
|
||||||
{Date{600, time.March, 1}, gDate(600, time.March, 4)},
|
|
||||||
{Date{700, time.February, 28}, gDate(700, time.March, 3)},
|
|
||||||
{Date{700, time.February, 29}, gDate(700, time.March, 4)},
|
|
||||||
{Date{700, time.March, 1}, gDate(700, time.March, 5)},
|
|
||||||
{Date{900, time.February, 28}, gDate(900, time.March, 4)},
|
|
||||||
{Date{900, time.February, 29}, gDate(900, time.March, 5)},
|
|
||||||
{Date{900, time.March, 1}, gDate(900, time.March, 6)},
|
|
||||||
{Date{1000, time.February, 28}, gDate(1000, time.March, 5)},
|
|
||||||
{Date{1000, time.February, 29}, gDate(1000, time.March, 6)},
|
|
||||||
{Date{1000, time.March, 1}, gDate(1000, time.March, 7)},
|
|
||||||
{Date{1100, time.February, 28}, gDate(1100, time.March, 6)},
|
|
||||||
{Date{1100, time.February, 29}, gDate(1100, time.March, 7)},
|
|
||||||
{Date{1100, time.March, 1}, gDate(1100, time.March, 8)},
|
|
||||||
{Date{1300, time.February, 28}, gDate(1300, time.March, 7)},
|
|
||||||
{Date{1300, time.February, 29}, gDate(1300, time.March, 8)},
|
|
||||||
{Date{1300, time.March, 1}, gDate(1300, time.March, 9)},
|
|
||||||
{Date{1400, time.February, 28}, gDate(1400, time.March, 8)},
|
|
||||||
{Date{1400, time.February, 29}, gDate(1400, time.March, 9)},
|
|
||||||
{Date{1400, time.March, 1}, gDate(1400, time.March, 10)},
|
|
||||||
{Date{1500, time.February, 28}, gDate(1500, time.March, 9)},
|
|
||||||
{Date{1500, time.February, 29}, gDate(1500, time.March, 10)},
|
|
||||||
{Date{1500, time.March, 1}, gDate(1500, time.March, 11)},
|
|
||||||
{Date{1582, time.October, 4}, gDate(1582, time.October, 14)},
|
|
||||||
{Date{1582, time.October, 5}, gDate(1582, time.October, 15)},
|
|
||||||
{Date{1582, time.October, 6}, gDate(1582, time.October, 16)},
|
|
||||||
{Date{1700, time.February, 18}, gDate(1700, time.February, 28)},
|
|
||||||
{Date{1700, time.February, 19}, gDate(1700, time.March, 1)},
|
|
||||||
{Date{1700, time.February, 28}, gDate(1700, time.March, 10)},
|
|
||||||
{Date{1700, time.February, 29}, gDate(1700, time.March, 11)},
|
|
||||||
{Date{1700, time.March, 1}, gDate(1700, time.March, 12)},
|
|
||||||
{Date{1800, time.February, 17}, gDate(1800, time.February, 28)},
|
|
||||||
{Date{1800, time.February, 18}, gDate(1800, time.March, 1)},
|
|
||||||
{Date{1800, time.February, 28}, gDate(1800, time.March, 11)},
|
|
||||||
{Date{1800, time.February, 29}, gDate(1800, time.March, 12)},
|
|
||||||
{Date{1800, time.March, 1}, gDate(1800, time.March, 13)},
|
|
||||||
{Date{1900, time.February, 16}, gDate(1900, time.February, 28)},
|
|
||||||
{Date{1900, time.February, 17}, gDate(1900, time.March, 1)},
|
|
||||||
{Date{1900, time.February, 28}, gDate(1900, time.March, 12)},
|
|
||||||
{Date{1900, time.February, 29}, gDate(1900, time.March, 13)},
|
|
||||||
{Date{1900, time.March, 1}, gDate(1900, time.March, 14)},
|
|
||||||
{Date{2100, time.February, 15}, gDate(2100, time.February, 28)},
|
|
||||||
{Date{2100, time.February, 16}, gDate(2100, time.March, 1)},
|
|
||||||
{Date{2100, time.February, 28}, gDate(2100, time.March, 13)},
|
|
||||||
{Date{2100, time.February, 29}, gDate(2100, time.March, 14)},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
testname := fmt.Sprintf("%v, %v", tt.d, tt.want)
|
|
||||||
t.Run(testname, func(t *testing.T) {
|
|
||||||
ans := ToTime(tt.d)
|
|
||||||
if ans != tt.want {
|
|
||||||
t.Errorf("got %v, want %v", ans, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue