2019-08-15 17:46:21 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2019-08-15 17:46:21 +03:00
package timeutil
import (
"fmt"
"html/template"
"strings"
"time"
2022-06-26 17:19:22 +03:00
"code.gitea.io/gitea/modules/translation"
2019-08-15 17:46:21 +03:00
)
// Seconds-based time units
const (
Minute = 60
Hour = 60 * Minute
Day = 24 * Hour
Week = 7 * Day
Month = 30 * Day
Year = 12 * Month
)
2022-06-26 17:19:22 +03:00
func computeTimeDiffFloor ( diff int64 , lang translation . Locale ) ( int64 , string ) {
2023-04-22 21:53:00 +03:00
var diffStr string
2019-08-15 17:46:21 +03:00
switch {
case diff <= 0 :
diff = 0
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.now" )
2019-08-15 17:46:21 +03:00
case diff < 2 :
diff = 0
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1s" )
2019-08-15 17:46:21 +03:00
case diff < 1 * Minute :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.seconds" , diff )
2019-08-15 17:46:21 +03:00
diff = 0
case diff < 2 * Minute :
diff -= 1 * Minute
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1m" )
2019-08-15 17:46:21 +03:00
case diff < 1 * Hour :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.minutes" , diff / Minute )
2019-08-15 17:46:21 +03:00
diff -= diff / Minute * Minute
case diff < 2 * Hour :
diff -= 1 * Hour
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1h" )
2019-08-15 17:46:21 +03:00
case diff < 1 * Day :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.hours" , diff / Hour )
2019-08-15 17:46:21 +03:00
diff -= diff / Hour * Hour
case diff < 2 * Day :
diff -= 1 * Day
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1d" )
2019-08-15 17:46:21 +03:00
case diff < 1 * Week :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.days" , diff / Day )
2019-08-15 17:46:21 +03:00
diff -= diff / Day * Day
case diff < 2 * Week :
diff -= 1 * Week
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1w" )
2019-08-15 17:46:21 +03:00
case diff < 1 * Month :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.weeks" , diff / Week )
2019-08-15 17:46:21 +03:00
diff -= diff / Week * Week
case diff < 2 * Month :
diff -= 1 * Month
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1mon" )
2019-08-15 17:46:21 +03:00
case diff < 1 * Year :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.months" , diff / Month )
2019-08-15 17:46:21 +03:00
diff -= diff / Month * Month
case diff < 2 * Year :
diff -= 1 * Year
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.1y" )
2019-08-15 17:46:21 +03:00
default :
2022-06-26 17:19:22 +03:00
diffStr = lang . Tr ( "tool.years" , diff / Year )
2019-08-15 17:46:21 +03:00
diff -= ( diff / Year ) * Year
}
return diff , diffStr
}
// MinutesToFriendly returns a user friendly string with number of minutes
// converted to hours and minutes.
2022-06-26 17:19:22 +03:00
func MinutesToFriendly ( minutes int , lang translation . Locale ) string {
2019-08-15 17:46:21 +03:00
duration := time . Duration ( minutes ) * time . Minute
return TimeSincePro ( time . Now ( ) . Add ( - duration ) , lang )
}
// TimeSincePro calculates the time interval and generate full user-friendly string.
2022-06-26 17:19:22 +03:00
func TimeSincePro ( then time . Time , lang translation . Locale ) string {
2019-08-15 17:46:21 +03:00
return timeSincePro ( then , time . Now ( ) , lang )
}
2022-06-26 17:19:22 +03:00
func timeSincePro ( then , now time . Time , lang translation . Locale ) string {
2019-08-15 17:46:21 +03:00
diff := now . Unix ( ) - then . Unix ( )
if then . After ( now ) {
2022-06-26 17:19:22 +03:00
return lang . Tr ( "tool.future" )
2019-08-15 17:46:21 +03:00
}
if diff == 0 {
2022-06-26 17:19:22 +03:00
return lang . Tr ( "tool.now" )
2019-08-15 17:46:21 +03:00
}
var timeStr , diffStr string
for {
if diff == 0 {
break
}
2021-01-28 15:29:22 +03:00
diff , diffStr = computeTimeDiffFloor ( diff , lang )
2019-08-15 17:46:21 +03:00
timeStr += ", " + diffStr
}
return strings . TrimPrefix ( timeStr , ", " )
}
2023-04-15 14:01:54 +03:00
func timeSinceUnix ( then , now time . Time , lang translation . Locale ) template . HTML {
2023-04-25 22:48:30 +03:00
friendlyText := then . Format ( "2006-01-02 15:04:05 -07:00" )
2023-04-15 14:01:54 +03:00
// document: https://github.com/github/relative-time-element
attrs := ` tense="past" `
isFuture := now . Before ( then )
if isFuture {
attrs = ` tense="future" `
}
// declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip
htm := fmt . Sprintf ( ` <relative-time class="time-since" prefix="" %s datetime="%s" data-tooltip-content data-tooltip-interactive="true">%s</relative-time> ` ,
attrs , then . Format ( time . RFC3339 ) , friendlyText )
return template . HTML ( htm )
}
2023-04-11 02:01:20 +03:00
// TimeSince renders relative time HTML given a time.Time
2022-06-26 17:19:22 +03:00
func TimeSince ( then time . Time , lang translation . Locale ) template . HTML {
2023-04-15 14:01:54 +03:00
return timeSinceUnix ( then , time . Now ( ) , lang )
2019-08-15 17:46:21 +03:00
}
2023-04-11 02:01:20 +03:00
// TimeSinceUnix renders relative time HTML given a TimeStamp
2022-06-26 17:19:22 +03:00
func TimeSinceUnix ( then TimeStamp , lang translation . Locale ) template . HTML {
2023-04-11 02:01:20 +03:00
return TimeSince ( then . AsLocalTime ( ) , lang )
2019-08-15 17:46:21 +03:00
}