github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/timeutil/human.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package timeutil 21 22 import ( 23 "fmt" 24 "time" 25 26 "github.com/snapcore/snapd/i18n" 27 ) 28 29 // start-of-day 30 func sod(t time.Time) time.Time { 31 y, m, d := t.Date() 32 return time.Date(y, m, d, 0, 0, 0, 0, t.Location()) 33 } 34 35 // Human turns the time into a relative expression of time meant for human 36 // consumption. 37 // Human(t) --> "today at 07:47" 38 func Human(then time.Time) string { 39 return humanTimeSince(then.Local(), time.Now().Local(), 60) 40 } 41 42 func delta(then, now time.Time) int { 43 if then.After(now) { 44 return -delta(now, then) 45 } 46 47 then = sod(then) 48 now = sod(now) 49 50 n := int(then.Sub(now).Hours() / 24) 51 now = now.AddDate(0, 0, n) 52 for then.Before(now) { 53 then = then.AddDate(0, 0, 1) 54 n-- 55 } 56 return n 57 } 58 59 func humanTimeSince(then, now time.Time, cutoffDays int) string { 60 d := delta(then, now) 61 switch { 62 case d < -cutoffDays || d > cutoffDays: 63 return then.Format("2006-01-02") 64 case d < -1: 65 // TRANSLATORS: %d will be at least 2; the singular is only included to help gettext 66 return fmt.Sprintf(then.Format(i18n.NG("%d day ago, at 15:04 MST", "%d days ago, at 15:04 MST", -d)), -d) 67 case d == -1: 68 return then.Format(i18n.G("yesterday at 15:04 MST")) 69 case d == 0: 70 return then.Format(i18n.G("today at 15:04 MST")) 71 case d == 1: 72 return then.Format(i18n.G("tomorrow at 15:04 MST")) 73 case d > 1: 74 // TRANSLATORS: %d will be at least 2; the singular is only included to help gettext 75 return fmt.Sprintf(then.Format(i18n.NG("in %d day, at 15:04 MST", "in %d days, at 15:04 MST", d)), d) 76 default: 77 // the following message is brought to you by Joel Armando, the self-described awesome and sexy mathematician. 78 panic("you have broken the law of trichotomy! ℤ is no longer totally ordered! chaos ensues!") 79 } 80 }