Display ui time with customize time location (#7792)

* display ui time with customize time location

* fix lint

* rename UILocation to DefaultUILocation

* move time related functions to modules/timeutil

* fix tests

* fix tests

* fix build

* fix swagger
tokarchuk/v1.17
Lunny Xiao 5 years ago committed by GitHub
parent 5a44be627c
commit 85202d4784
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      custom/conf/app.ini.sample
  2. 4
      docs/content/doc/advanced/config-cheat-sheet.en-us.md
  3. 4
      docs/content/doc/advanced/config-cheat-sheet.zh-cn.md
  4. 4
      models/action.go
  5. 4
      models/admin.go
  6. 4
      models/attachment.go
  7. 7
      models/branches.go
  8. 6
      models/commit_status.go
  9. 18
      models/gpg_key.go
  10. 6
      models/gpg_key_test.go
  11. 17
      models/issue.go
  12. 17
      models/issue_comment.go
  13. 6
      models/issue_dependency.go
  14. 9
      models/issue_milestone.go
  15. 6
      models/issue_milestone_test.go
  16. 4
      models/issue_reaction.go
  17. 4
      models/issue_stopwatch.go
  18. 4
      models/issue_stopwatch_test.go
  19. 2
      models/issue_tracked_time.go
  20. 6
      models/issue_watch.go
  21. 4
      models/lfs.go
  22. 14
      models/login_source.go
  23. 7
      models/mail.go
  24. 4
      models/migrations/v54.go
  25. 4
      models/migrations/v57.go
  26. 14
      models/migrations/v64.go
  27. 7
      models/migrations/v65.go
  28. 10
      models/migrations/v71.go
  29. 6
      models/migrations/v72.go
  30. 4
      models/migrations/v76.go
  31. 4
      models/migrations/v83.go
  32. 10
      models/migrations/v85.go
  33. 6
      models/notification.go
  34. 17
      models/oauth2_application.go
  35. 6
      models/pull.go
  36. 8
      models/release.go
  37. 8
      models/repo.go
  38. 13
      models/repo_mirror.go
  39. 4
      models/repo_unit.go
  40. 8
      models/review.go
  41. 16
      models/ssh_key.go
  42. 12
      models/token.go
  43. 6
      models/topic.go
  44. 12
      models/twofactor.go
  45. 6
      models/u2f.go
  46. 6
      models/update.go
  47. 9
      models/user.go
  48. 6
      models/user_heatmap.go
  49. 7
      models/webhook.go
  50. 6
      modules/auth/auth.go
  51. 151
      modules/base/tool.go
  52. 149
      modules/base/tool_test.go
  53. 26
      modules/migrations/gitea.go
  54. 4
      modules/pull/merge.go
  55. 27
      modules/setting/setting.go
  56. 10
      modules/templates/helper.go
  57. 36
      modules/timeutil/language.go
  58. 164
      modules/timeutil/since.go
  59. 163
      modules/timeutil/since_test.go
  60. 27
      modules/timeutil/timestamp.go
  61. 4
      public/js/index.js
  62. 3
      routers/admin/admin.go
  63. 13
      routers/api/v1/repo/issue.go
  64. 7
      routers/api/v1/repo/milestone.go
  65. 10
      routers/api/v1/repo/pull.go
  66. 5
      routers/dev/template.go
  67. 4
      routers/private/key.go
  68. 5
      routers/repo/blame.go
  69. 4
      routers/repo/http.go
  70. 7
      routers/repo/milestone.go
  71. 10
      routers/repo/setting.go
  72. 5
      routers/repo/wiki.go
  73. 11
      routers/user/auth.go
  74. 3
      routers/user/auth_openid.go
  75. 8
      routers/user/oauth.go
  76. 3
      routers/user/setting/account.go
  77. 2
      templates/swagger/v1_json.tmpl

@ -547,6 +547,9 @@ MAX_FILES = 5
; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano ; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
; For more information about the format see http://golang.org/pkg/time/#pkg-constants ; For more information about the format see http://golang.org/pkg/time/#pkg-constants
FORMAT = FORMAT =
; Location the UI time display i.e. Asia/Shanghai
; Empty means server's location setting
DEFAULT_UI_LOCATION =
[log] [log]
ROOT_PATH = ROOT_PATH =

@ -503,6 +503,10 @@ Two special environment variables are passed to the render command:
- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links. - `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links.
- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths. - `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths.
## Time (`time`)
- `FORMAT`: Time format to diplay on UI. i.e. RFC1123 or 2006-01-02 15:04:05
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Shanghai/Asia
## Other (`other`) ## Other (`other`)
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer. - `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.

@ -237,7 +237,9 @@ IS_INPUT_FILE = false
- RENDER_COMMAND: 工具的命令行命令及参数。 - RENDER_COMMAND: 工具的命令行命令及参数。
- IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。 - IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。
## Time (`time`)
- `FORMAT`: 显示在界面上的时间格式。比如: RFC1123 或者 2006-01-02 15:04:05
- `DEFAULT_UI_LOCATION`: 默认显示在界面上的时区,默认为本地时区。比如: Asia/Shanghai
## Other (`other`) ## Other (`other`)

@ -20,7 +20,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"xorm.io/builder" "xorm.io/builder"
@ -93,7 +93,7 @@ type Action struct {
RefName string RefName string
IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"` IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"`
Content string `xorm:"TEXT"` Content string `xorm:"TEXT"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
} }
// GetOpType gets the ActionType of this action. // GetOpType gets the ActionType of this action.

@ -9,7 +9,7 @@ import (
"os" "os"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
) )
@ -27,7 +27,7 @@ type Notice struct {
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
Type NoticeType Type NoticeType
Description string `xorm:"TEXT"` Description string `xorm:"TEXT"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
} }
// TrStr returns a translation format string. // TrStr returns a translation format string.

@ -12,7 +12,7 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
gouuid "github.com/satori/go.uuid" gouuid "github.com/satori/go.uuid"
@ -29,7 +29,7 @@ type Attachment struct {
Name string Name string
DownloadCount int64 `xorm:"DEFAULT 0"` DownloadCount int64 `xorm:"DEFAULT 0"`
Size int64 `xorm:"DEFAULT 0"` Size int64 `xorm:"DEFAULT 0"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
} }
// IncreaseDownloadCount is update download count + 1 // IncreaseDownloadCount is update download count + 1

@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/Unknwon/com" "github.com/Unknwon/com"
@ -38,8 +39,8 @@ type ProtectedBranch struct {
ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"`
ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix util.TimeStamp `xorm:"updated"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
} }
// IsProtected returns if the branch is protected // IsProtected returns if the branch is protected
@ -380,7 +381,7 @@ type DeletedBranch struct {
Commit string `xorm:"UNIQUE(s) NOT NULL"` Commit string `xorm:"UNIQUE(s) NOT NULL"`
DeletedByID int64 `xorm:"INDEX"` DeletedByID int64 `xorm:"INDEX"`
DeletedBy *User `xorm:"-"` DeletedBy *User `xorm:"-"`
DeletedUnix util.TimeStamp `xorm:"INDEX created"` DeletedUnix timeutil.TimeStamp `xorm:"INDEX created"`
} }
// AddDeletedBranch adds a deleted branch to the database // AddDeletedBranch adds a deleted branch to the database

@ -13,7 +13,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -66,8 +66,8 @@ type CommitStatus struct {
Creator *User `xorm:"-"` Creator *User `xorm:"-"`
CreatorID int64 CreatorID int64
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
func (status *CommitStatus) loadRepo(e Engine) (err error) { func (status *CommitStatus) loadRepo(e Engine) (err error) {

@ -17,7 +17,7 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/keybase/go-crypto/openpgp" "github.com/keybase/go-crypto/openpgp"
@ -32,9 +32,9 @@ type GPGKey struct {
KeyID string `xorm:"INDEX CHAR(16) NOT NULL"` KeyID string `xorm:"INDEX CHAR(16) NOT NULL"`
PrimaryKeyID string `xorm:"CHAR(16)"` PrimaryKeyID string `xorm:"CHAR(16)"`
Content string `xorm:"TEXT NOT NULL"` Content string `xorm:"TEXT NOT NULL"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
ExpiredUnix util.TimeStamp ExpiredUnix timeutil.TimeStamp
AddedUnix util.TimeStamp AddedUnix timeutil.TimeStamp
SubsKey []*GPGKey `xorm:"-"` SubsKey []*GPGKey `xorm:"-"`
Emails []*EmailAddress Emails []*EmailAddress
CanSign bool CanSign bool
@ -51,7 +51,7 @@ type GPGKeyImport struct {
// BeforeInsert will be invoked by XORM before inserting a record // BeforeInsert will be invoked by XORM before inserting a record
func (key *GPGKey) BeforeInsert() { func (key *GPGKey) BeforeInsert() {
key.AddedUnix = util.TimeStampNow() key.AddedUnix = timeutil.TimeStampNow()
} }
// AfterLoad is invoked from XORM after setting the values of all fields of this object. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
@ -223,8 +223,8 @@ func parseSubGPGKey(ownerID int64, primaryID string, pubkey *packet.PublicKey, e
KeyID: pubkey.KeyIdString(), KeyID: pubkey.KeyIdString(),
PrimaryKeyID: primaryID, PrimaryKeyID: primaryID,
Content: content, Content: content,
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()),
ExpiredUnix: util.TimeStamp(expiry.Unix()), ExpiredUnix: timeutil.TimeStamp(expiry.Unix()),
CanSign: pubkey.CanSign(), CanSign: pubkey.CanSign(),
CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(), CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(),
CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(), CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(),
@ -301,8 +301,8 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
KeyID: pubkey.KeyIdString(), KeyID: pubkey.KeyIdString(),
PrimaryKeyID: "", PrimaryKeyID: "",
Content: content, Content: content,
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()),
ExpiredUnix: util.TimeStamp(expiry.Unix()), ExpiredUnix: timeutil.TimeStamp(expiry.Unix()),
Emails: emails, Emails: emails,
SubsKey: subkeys, SubsKey: subkeys,
CanSign: pubkey.CanSign(), CanSign: pubkey.CanSign(),

@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -112,7 +112,7 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
key := &GPGKey{ key := &GPGKey{
KeyID: pubkey.KeyIdString(), KeyID: pubkey.KeyIdString(),
Content: content, Content: content,
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()),
CanSign: pubkey.CanSign(), CanSign: pubkey.CanSign(),
CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(), CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(),
CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(), CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(),
@ -122,7 +122,7 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
cannotsignkey := &GPGKey{ cannotsignkey := &GPGKey{
KeyID: pubkey.KeyIdString(), KeyID: pubkey.KeyIdString(),
Content: content, Content: content,
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()),
CanSign: false, CanSign: false,
CanEncryptComms: false, CanEncryptComms: false,
CanEncryptStorage: false, CanEncryptStorage: false,

@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/Unknwon/com" "github.com/Unknwon/com"
@ -49,11 +50,11 @@ type Issue struct {
NumComments int NumComments int
Ref string Ref string
DeadlineUnix util.TimeStamp `xorm:"INDEX"` DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
ClosedUnix util.TimeStamp `xorm:"INDEX"` ClosedUnix timeutil.TimeStamp `xorm:"INDEX"`
Attachments []*Attachment `xorm:"-"` Attachments []*Attachment `xorm:"-"`
Comments []*Comment `xorm:"-"` Comments []*Comment `xorm:"-"`
@ -90,7 +91,7 @@ func (issue *Issue) loadTotalTimes(e Engine) (err error) {
// IsOverdue checks if the issue is overdue // IsOverdue checks if the issue is overdue
func (issue *Issue) IsOverdue() bool { func (issue *Issue) IsOverdue() bool {
return util.TimeStampNow() >= issue.DeadlineUnix return timeutil.TimeStampNow() >= issue.DeadlineUnix
} }
// LoadRepo loads issue's repository // LoadRepo loads issue's repository
@ -744,7 +745,7 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (er
issue.IsClosed = isClosed issue.IsClosed = isClosed
if isClosed { if isClosed {
issue.ClosedUnix = util.TimeStampNow() issue.ClosedUnix = timeutil.TimeStampNow()
} else { } else {
issue.ClosedUnix = 0 issue.ClosedUnix = 0
} }
@ -991,7 +992,7 @@ func (issue *Issue) GetTasksDone() int {
} }
// GetLastEventTimestamp returns the last user visible event timestamp, either the creation of this issue or the close. // GetLastEventTimestamp returns the last user visible event timestamp, either the creation of this issue or the close.
func (issue *Issue) GetLastEventTimestamp() util.TimeStamp { func (issue *Issue) GetLastEventTimestamp() timeutil.TimeStamp {
if issue.IsClosed { if issue.IsClosed {
return issue.ClosedUnix return issue.ClosedUnix
} }
@ -1794,7 +1795,7 @@ func UpdateIssue(issue *Issue) error {
} }
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it. // UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.
func UpdateIssueDeadline(issue *Issue, deadlineUnix util.TimeStamp, doer *User) (err error) { func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *User) (err error) {
// if the deadline hasn't changed do nothing // if the deadline hasn't changed do nothing
if issue.DeadlineUnix == deadlineUnix { if issue.DeadlineUnix == deadlineUnix {

@ -12,17 +12,16 @@ import (
"strings" "strings"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"xorm.io/builder" "xorm.io/builder"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/util"
) )
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference. // CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
@ -130,8 +129,8 @@ type Comment struct {
// Path represents the 4 lines of code cemented by this comment // Path represents the 4 lines of code cemented by this comment
Patch string `xorm:"TEXT"` Patch string `xorm:"TEXT"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
// Reference issue in commit message // Reference issue in commit message
CommitSHA string `xorm:"VARCHAR(40)"` CommitSHA string `xorm:"VARCHAR(40)"`
@ -711,7 +710,7 @@ func createAssigneeComment(e *xorm.Session, doer *User, repo *Repository, issue
}) })
} }
func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix util.TimeStamp) (*Comment, error) { func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix timeutil.TimeStamp) (*Comment, error) {
var content string var content string
var commentType CommentType var commentType CommentType

@ -7,7 +7,7 @@ package models
import ( import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// IssueDependency represents an issue dependency // IssueDependency represents an issue dependency
@ -16,8 +16,8 @@ type IssueDependency struct {
UserID int64 `xorm:"NOT NULL"` UserID int64 `xorm:"NOT NULL"`
IssueID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"` IssueID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"`
DependencyID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"` DependencyID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix util.TimeStamp `xorm:"updated"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
} }
// DependencyType Defines Dependency Type Constants // DependencyType Defines Dependency Type Constants

@ -10,7 +10,8 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -29,8 +30,8 @@ type Milestone struct {
IsOverdue bool `xorm:"-"` IsOverdue bool `xorm:"-"`
DeadlineString string `xorm:"-"` DeadlineString string `xorm:"-"`
DeadlineUnix util.TimeStamp DeadlineUnix timeutil.TimeStamp
ClosedDateUnix util.TimeStamp ClosedDateUnix timeutil.TimeStamp
TotalTrackedTime int64 `xorm:"-"` TotalTrackedTime int64 `xorm:"-"`
} }
@ -53,7 +54,7 @@ func (m *Milestone) AfterLoad() {
} }
m.DeadlineString = m.DeadlineUnix.Format("2006-01-02") m.DeadlineString = m.DeadlineUnix.Format("2006-01-02")
if util.TimeStampNow() >= m.DeadlineUnix { if timeutil.TimeStampNow() >= m.DeadlineUnix {
m.IsOverdue = true m.IsOverdue = true
} }
} }

@ -10,7 +10,7 @@ import (
"time" "time"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -29,7 +29,7 @@ func TestMilestone_APIFormat(t *testing.T) {
IsClosed: false, IsClosed: false,
NumOpenIssues: 5, NumOpenIssues: 5,
NumClosedIssues: 6, NumClosedIssues: 6,
DeadlineUnix: util.TimeStamp(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC).Unix()), DeadlineUnix: timeutil.TimeStamp(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC).Unix()),
} }
assert.Equal(t, api.Milestone{ assert.Equal(t, api.Milestone{
ID: milestone.ID, ID: milestone.ID,
@ -237,7 +237,7 @@ func TestChangeMilestoneIssueStats(t *testing.T) {
"is_closed=0").(*Issue) "is_closed=0").(*Issue)
issue.IsClosed = true issue.IsClosed = true
issue.ClosedUnix = util.TimeStampNow() issue.ClosedUnix = timeutil.TimeStampNow()
_, err := x.Cols("is_closed", "closed_unix").Update(issue) _, err := x.Cols("is_closed", "closed_unix").Update(issue)
assert.NoError(t, err) assert.NoError(t, err)
assert.NoError(t, changeMilestoneIssueStats(x.NewSession(), issue)) assert.NoError(t, changeMilestoneIssueStats(x.NewSession(), issue))

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"xorm.io/builder" "xorm.io/builder"
@ -23,7 +23,7 @@ type Reaction struct {
CommentID int64 `xorm:"INDEX UNIQUE(s)"` CommentID int64 `xorm:"INDEX UNIQUE(s)"`
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"` UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
User *User `xorm:"-"` User *User `xorm:"-"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
} }
// FindReactionsOptions describes the conditions to Find reactions // FindReactionsOptions describes the conditions to Find reactions

@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"time" "time"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// Stopwatch represents a stopwatch for time tracking. // Stopwatch represents a stopwatch for time tracking.
@ -16,7 +16,7 @@ type Stopwatch struct {
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
IssueID int64 `xorm:"INDEX"` IssueID int64 `xorm:"INDEX"`
UserID int64 `xorm:"INDEX"` UserID int64 `xorm:"INDEX"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
} }
func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool, err error) { func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool, err error) {

@ -3,7 +3,7 @@ package models
import ( import (
"testing" "testing"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -63,7 +63,7 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) {
assert.NoError(t, CreateOrStopIssueStopwatch(user3, issue1)) assert.NoError(t, CreateOrStopIssueStopwatch(user3, issue1))
sw := AssertExistsAndLoadBean(t, &Stopwatch{UserID: 3, IssueID: 1}).(*Stopwatch) sw := AssertExistsAndLoadBean(t, &Stopwatch{UserID: 3, IssueID: 1}).(*Stopwatch)
assert.Equal(t, true, sw.CreatedUnix <= util.TimeStampNow()) assert.Equal(t, true, sw.CreatedUnix <= timeutil.TimeStampNow())
assert.NoError(t, CreateOrStopIssueStopwatch(user2, issue2)) assert.NoError(t, CreateOrStopIssueStopwatch(user2, issue2))
AssertNotExistsBean(t, &Stopwatch{UserID: 2, IssueID: 2}) AssertNotExistsBean(t, &Stopwatch{UserID: 2, IssueID: 2})

@ -26,7 +26,7 @@ type TrackedTime struct {
// AfterLoad is invoked from XORM after setting the values of all fields of this object. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
func (t *TrackedTime) AfterLoad() { func (t *TrackedTime) AfterLoad() {
t.Created = time.Unix(t.CreatedUnix, 0).In(setting.UILocation) t.Created = time.Unix(t.CreatedUnix, 0).In(setting.DefaultUILocation)
} }
// APIFormat converts TrackedTime to API format // APIFormat converts TrackedTime to API format

@ -4,7 +4,7 @@
package models package models
import "code.gitea.io/gitea/modules/util" import "code.gitea.io/gitea/modules/timeutil"
// IssueWatch is connection request for receiving issue notification. // IssueWatch is connection request for receiving issue notification.
type IssueWatch struct { type IssueWatch struct {
@ -12,8 +12,8 @@ type IssueWatch struct {
UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` UserID int64 `xorm:"UNIQUE(watch) NOT NULL"`
IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"`
IsWatching bool `xorm:"NOT NULL"` IsWatching bool `xorm:"NOT NULL"`
CreatedUnix util.TimeStamp `xorm:"created NOT NULL"` CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
UpdatedUnix util.TimeStamp `xorm:"updated NOT NULL"` UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL"`
} }
// CreateOrUpdateIssueWatch set watching for a user and issue // CreateOrUpdateIssueWatch set watching for a user and issue

@ -7,7 +7,7 @@ import (
"fmt" "fmt"
"io" "io"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// LFSMetaObject stores metadata for LFS tracked files. // LFSMetaObject stores metadata for LFS tracked files.
@ -17,7 +17,7 @@ type LFSMetaObject struct {
Size int64 `xorm:"NOT NULL"` Size int64 `xorm:"NOT NULL"`
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
Existing bool `xorm:"-"` Existing bool `xorm:"-"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
} }
// Pointer returns the string representation of an LFS pointer file // Pointer returns the string representation of an LFS pointer file

@ -14,16 +14,16 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"xorm.io/core"
"code.gitea.io/gitea/modules/auth/ldap" "code.gitea.io/gitea/modules/auth/ldap"
"code.gitea.io/gitea/modules/auth/oauth2" "code.gitea.io/gitea/modules/auth/oauth2"
"code.gitea.io/gitea/modules/auth/pam" "code.gitea.io/gitea/modules/auth/pam"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"xorm.io/core"
) )
// LoginType represents an login type. // LoginType represents an login type.
@ -148,8 +148,8 @@ type LoginSource struct {
IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"` IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
Cfg core.Conversion `xorm:"TEXT"` Cfg core.Conversion `xorm:"TEXT"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// Cell2Int64 converts a xorm.Cell type to int64, // Cell2Int64 converts a xorm.Cell type to int64,

@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"gopkg.in/gomail.v2" "gopkg.in/gomail.v2"
) )
@ -47,8 +48,8 @@ func SendTestMail(email string) error {
func SendUserMail(language string, u *User, tpl base.TplName, code, subject, info string) { func SendUserMail(language string, u *User, tpl base.TplName, code, subject, info string) {
data := map[string]interface{}{ data := map[string]interface{}{
"DisplayName": u.DisplayName(), "DisplayName": u.DisplayName(),
"ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives, language), "ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, language),
"ResetPwdCodeLives": base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, language), "ResetPwdCodeLives": timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, language),
"Code": code, "Code": code,
} }
@ -85,7 +86,7 @@ func SendResetPasswordMail(locale Locale, u *User) {
func SendActivateEmailMail(locale Locale, u *User, email *EmailAddress) { func SendActivateEmailMail(locale Locale, u *User, email *EmailAddress) {
data := map[string]interface{}{ data := map[string]interface{}{
"DisplayName": u.DisplayName(), "DisplayName": u.DisplayName(),
"ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives, locale.Language()), "ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale.Language()),
"Code": u.GenerateEmailActivateCode(email.Email), "Code": u.GenerateEmailActivateCode(email.Email),
"Email": email.Email, "Email": email.Email,
} }

@ -7,7 +7,7 @@ package migrations
import ( import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -19,7 +19,7 @@ func addPullRequestOptions(x *xorm.Engine) error {
RepoID int64 `xorm:"INDEX(s)"` RepoID int64 `xorm:"INDEX(s)"`
Type int `xorm:"INDEX(s)"` Type int `xorm:"INDEX(s)"`
Config map[string]interface{} `xorm:"JSON"` Config map[string]interface{} `xorm:"JSON"`
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
} }
sess := x.NewSession() sess := x.NewSession()

@ -7,7 +7,7 @@ package migrations
import ( import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -15,7 +15,7 @@ import (
func addIssueClosedTime(x *xorm.Engine) error { func addIssueClosedTime(x *xorm.Engine) error {
// Issue see models/issue.go // Issue see models/issue.go
type Issue struct { type Issue struct {
ClosedUnix util.TimeStamp `xorm:"INDEX"` ClosedUnix timeutil.TimeStamp `xorm:"INDEX"`
} }
if err := x.Sync2(new(Issue)); err != nil { if err := x.Sync2(new(Issue)); err != nil {

@ -5,7 +5,7 @@
package migrations package migrations
import ( import (
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -27,10 +27,10 @@ func addMultipleAssignees(x *xorm.Engine) error {
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not. IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
NumComments int NumComments int
DeadlineUnix util.TimeStamp `xorm:"INDEX"` DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
ClosedUnix util.TimeStamp `xorm:"INDEX"` ClosedUnix timeutil.TimeStamp `xorm:"INDEX"`
} }
// Updated the comment table // Updated the comment table
@ -53,8 +53,8 @@ func addMultipleAssignees(x *xorm.Engine) error {
Content string `xorm:"TEXT"` Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"` RenderedContent string `xorm:"-"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
// Reference issue in commit message // Reference issue in commit message
CommitSHA string `xorm:"VARCHAR(40)"` CommitSHA string `xorm:"VARCHAR(40)"`

@ -1,7 +1,8 @@
package migrations package migrations
import ( import (
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -12,8 +13,8 @@ func addU2FReg(x *xorm.Engine) error {
UserID int64 `xorm:"INDEX"` UserID int64 `xorm:"INDEX"`
Raw []byte Raw []byte
Counter uint32 Counter uint32
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
return x.Sync2(&U2FRegistration{}) return x.Sync2(&U2FRegistration{})
} }

@ -8,11 +8,11 @@ import (
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/pbkdf2"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/util"
) )
func addScratchHash(x *xorm.Engine) error { func addScratchHash(x *xorm.Engine) error {
@ -25,8 +25,8 @@ func addScratchHash(x *xorm.Engine) error {
ScratchSalt string ScratchSalt string
ScratchHash string ScratchHash string
LastUsedPasscode string `xorm:"VARCHAR(10)"` LastUsedPasscode string `xorm:"VARCHAR(10)"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
if err := x.Sync2(new(TwoFactor)); err != nil { if err := x.Sync2(new(TwoFactor)); err != nil {

@ -7,7 +7,7 @@ package migrations
import ( import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -20,8 +20,8 @@ func addReview(x *xorm.Engine) error {
ReviewerID int64 `xorm:"index"` ReviewerID int64 `xorm:"index"`
IssueID int64 `xorm:"index"` IssueID int64 `xorm:"index"`
Content string Content string
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
if err := x.Sync2(new(Review)); err != nil { if err := x.Sync2(new(Review)); err != nil {

@ -7,7 +7,7 @@ package migrations
import ( import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -19,7 +19,7 @@ func addPullRequestRebaseWithMerge(x *xorm.Engine) error {
RepoID int64 `xorm:"INDEX(s)"` RepoID int64 `xorm:"INDEX(s)"`
Type int `xorm:"INDEX(s)"` Type int `xorm:"INDEX(s)"`
Config map[string]interface{} `xorm:"JSON"` Config map[string]interface{} `xorm:"JSON"`
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
} }
sess := x.NewSession() sess := x.NewSession()

@ -5,7 +5,7 @@
package migrations package migrations
import ( import (
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
) )
@ -21,7 +21,7 @@ func addUploaderIDForAttachment(x *xorm.Engine) error {
Name string Name string
DownloadCount int64 `xorm:"DEFAULT 0"` DownloadCount int64 `xorm:"DEFAULT 0"`
Size int64 `xorm:"DEFAULT 0"` Size int64 `xorm:"DEFAULT 0"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
} }
return x.Sync2(new(Attachment)) return x.Sync2(new(Attachment))

@ -7,11 +7,11 @@ package migrations
import ( import (
"fmt" "fmt"
"github.com/go-xorm/xorm"
"code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm"
) )
func hashAppToken(x *xorm.Engine) error { func hashAppToken(x *xorm.Engine) error {
@ -26,8 +26,8 @@ func hashAppToken(x *xorm.Engine) error {
TokenSalt string TokenSalt string
TokenLastEight string `xorm:"token_last_eight"` TokenLastEight string `xorm:"token_last_eight"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
HasRecentActivity bool `xorm:"-"` HasRecentActivity bool `xorm:"-"`
HasUsed bool `xorm:"-"` HasUsed bool `xorm:"-"`
} }

@ -7,7 +7,7 @@ package models
import ( import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
type ( type (
@ -52,8 +52,8 @@ type Notification struct {
Issue *Issue `xorm:"-"` Issue *Issue `xorm:"-"`
Repository *Repository `xorm:"-"` Repository *Repository `xorm:"-"`
CreatedUnix util.TimeStamp `xorm:"created INDEX NOT NULL"` CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"`
UpdatedUnix util.TimeStamp `xorm:"updated INDEX NOT NULL"` UpdatedUnix timeutil.TimeStamp `xorm:"updated INDEX NOT NULL"`
} }
// CreateOrUpdateIssueNotifications creates an issue notification // CreateOrUpdateIssueNotifications creates an issue notification

@ -11,15 +11,14 @@ import (
"net/url" "net/url"
"time" "time"
"github.com/go-xorm/xorm"
uuid "github.com/satori/go.uuid"
"code.gitea.io/gitea/modules/secret" "code.gitea.io/gitea/modules/secret"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/go-xorm/xorm"
uuid "github.com/satori/go.uuid"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
@ -36,8 +35,8 @@ type OAuth2Application struct {
RedirectURIs []string `xorm:"redirect_uris JSON TEXT"` RedirectURIs []string `xorm:"redirect_uris JSON TEXT"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// TableName sets the table name to `oauth2_application` // TableName sets the table name to `oauth2_application`
@ -264,7 +263,7 @@ type OAuth2AuthorizationCode struct {
CodeChallenge string CodeChallenge string
CodeChallengeMethod string CodeChallengeMethod string
RedirectURI string RedirectURI string
ValidUntil util.TimeStamp `xorm:"index"` ValidUntil timeutil.TimeStamp `xorm:"index"`
} }
// TableName sets the table name to `oauth2_authorization_code` // TableName sets the table name to `oauth2_authorization_code`
@ -348,8 +347,8 @@ type OAuth2Grant struct {
Application *OAuth2Application `xorm:"-"` Application *OAuth2Application `xorm:"-"`
ApplicationID int64 `xorm:"INDEX unique(user_application)"` ApplicationID int64 `xorm:"INDEX unique(user_application)"`
Counter int64 `xorm:"NOT NULL DEFAULT 1"` Counter int64 `xorm:"NOT NULL DEFAULT 1"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix util.TimeStamp `xorm:"updated"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
} }
// TableName sets the table name to `oauth2_grant` // TableName sets the table name to `oauth2_grant`

@ -23,7 +23,7 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/sync" "code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
@ -76,7 +76,7 @@ type PullRequest struct {
MergedCommitID string `xorm:"VARCHAR(40)"` MergedCommitID string `xorm:"VARCHAR(40)"`
MergerID int64 `xorm:"INDEX"` MergerID int64 `xorm:"INDEX"`
Merger *User `xorm:"-"` Merger *User `xorm:"-"`
MergedUnix util.TimeStamp `xorm:"updated INDEX"` MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"`
} }
// Note: don't try to get Issue because will end up recursive querying. // Note: don't try to get Issue because will end up recursive querying.
@ -443,7 +443,7 @@ func (pr *PullRequest) manuallyMerged() bool {
} }
if commit != nil { if commit != nil {
pr.MergedCommitID = commit.ID.String() pr.MergedCommitID = commit.ID.String()
pr.MergedUnix = util.TimeStamp(commit.Author.When.Unix()) pr.MergedUnix = timeutil.TimeStamp(commit.Author.When.Unix())
pr.Status = PullRequestStatusManuallyMerged pr.Status = PullRequestStatusManuallyMerged
merger, _ := GetUserByEmail(commit.Author.Email) merger, _ := GetUserByEmail(commit.Author.Email)

@ -14,7 +14,7 @@ import (
"code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"xorm.io/builder" "xorm.io/builder"
) )
@ -38,7 +38,7 @@ type Release struct {
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"` IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
IsTag bool `xorm:"NOT NULL DEFAULT false"` IsTag bool `xorm:"NOT NULL DEFAULT false"`
Attachments []*Attachment `xorm:"-"` Attachments []*Attachment `xorm:"-"`
CreatedUnix util.TimeStamp `xorm:"INDEX"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX"`
} }
func (r *Release) loadAttributes(e Engine) error { func (r *Release) loadAttributes(e Engine) error {
@ -137,13 +137,13 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
} }
rel.Sha1 = commit.ID.String() rel.Sha1 = commit.ID.String()
rel.CreatedUnix = util.TimeStamp(commit.Author.When.Unix()) rel.CreatedUnix = timeutil.TimeStamp(commit.Author.When.Unix())
rel.NumCommits, err = commit.CommitsCount() rel.NumCommits, err = commit.CommitsCount()
if err != nil { if err != nil {
return fmt.Errorf("CommitsCount: %v", err) return fmt.Errorf("CommitsCount: %v", err)
} }
} else { } else {
rel.CreatedUnix = util.TimeStampNow() rel.CreatedUnix = timeutil.TimeStampNow()
} }
return nil return nil
} }

@ -34,7 +34,7 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/sync" "code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
@ -175,8 +175,8 @@ type Repository struct {
// Avatar: ID(10-20)-md5(32) - must fit into 64 symbols // Avatar: ID(10-20)-md5(32) - must fit into 64 symbols
Avatar string `xorm:"VARCHAR(64)"` Avatar string `xorm:"VARCHAR(64)"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// ColorFormat returns a colored string to represent this repo // ColorFormat returns a colored string to represent this repo
@ -971,7 +971,7 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
RepoID: repo.ID, RepoID: repo.ID,
Interval: setting.Mirror.DefaultInterval, Interval: setting.Mirror.DefaultInterval,
EnablePrune: true, EnablePrune: true,
NextUpdateUnix: util.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
}); err != nil { }); err != nil {
return repo, fmt.Errorf("InsertOne: %v", err) return repo, fmt.Errorf("InsertOne: %v", err)
} }

@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sync" "code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/Unknwon/com" "github.com/Unknwon/com"
@ -34,8 +35,8 @@ type Mirror struct {
Interval time.Duration Interval time.Duration
EnablePrune bool `xorm:"NOT NULL DEFAULT true"` EnablePrune bool `xorm:"NOT NULL DEFAULT true"`
UpdatedUnix util.TimeStamp `xorm:"INDEX"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX"`
NextUpdateUnix util.TimeStamp `xorm:"INDEX"` NextUpdateUnix timeutil.TimeStamp `xorm:"INDEX"`
address string `xorm:"-"` address string `xorm:"-"`
} }
@ -43,8 +44,8 @@ type Mirror struct {
// BeforeInsert will be invoked by XORM before inserting a record // BeforeInsert will be invoked by XORM before inserting a record
func (m *Mirror) BeforeInsert() { func (m *Mirror) BeforeInsert() {
if m != nil { if m != nil {
m.UpdatedUnix = util.TimeStampNow() m.UpdatedUnix = timeutil.TimeStampNow()
m.NextUpdateUnix = util.TimeStampNow() m.NextUpdateUnix = timeutil.TimeStampNow()
} }
} }
@ -64,7 +65,7 @@ func (m *Mirror) AfterLoad(session *xorm.Session) {
// ScheduleNextUpdate calculates and sets next update time. // ScheduleNextUpdate calculates and sets next update time.
func (m *Mirror) ScheduleNextUpdate() { func (m *Mirror) ScheduleNextUpdate() {
if m.Interval != 0 { if m.Interval != 0 {
m.NextUpdateUnix = util.TimeStampNow().AddDuration(m.Interval) m.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(m.Interval)
} else { } else {
m.NextUpdateUnix = 0 m.NextUpdateUnix = 0
} }
@ -277,7 +278,7 @@ func (m *Mirror) runSync() ([]*mirrorSyncResult, bool) {
cache.Remove(m.Repo.GetCommitsCountCacheKey(branches[i].Name, true)) cache.Remove(m.Repo.GetCommitsCountCacheKey(branches[i].Name, true))
} }
m.UpdatedUnix = util.TimeStampNow() m.UpdatedUnix = timeutil.TimeStampNow()
return parseRemoteUpdateOutput(output), true return parseRemoteUpdateOutput(output), true
} }

@ -7,7 +7,7 @@ package models
import ( import (
"encoding/json" "encoding/json"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
@ -20,7 +20,7 @@ type RepoUnit struct {
RepoID int64 `xorm:"INDEX(s)"` RepoID int64 `xorm:"INDEX(s)"`
Type UnitType `xorm:"INDEX(s)"` Type UnitType `xorm:"INDEX(s)"`
Config core.Conversion `xorm:"TEXT"` Config core.Conversion `xorm:"TEXT"`
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
} }
// UnitConfig describes common unit config // UnitConfig describes common unit config

@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"xorm.io/builder" "xorm.io/builder"
@ -56,8 +56,8 @@ type Review struct {
IssueID int64 `xorm:"index"` IssueID int64 `xorm:"index"`
Content string Content string
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
// CodeComments are the initial code comments of the review // CodeComments are the initial code comments of the review
CodeComments CodeComments `xorm:"-"` CodeComments CodeComments `xorm:"-"`
@ -279,7 +279,7 @@ func UpdateReview(r *Review) error {
type PullReviewersWithType struct { type PullReviewersWithType struct {
User `xorm:"extends"` User `xorm:"extends"`
Type ReviewType Type ReviewType
ReviewUpdatedUnix util.TimeStamp `xorm:"review_updated_unix"` ReviewUpdatedUnix timeutil.TimeStamp `xorm:"review_updated_unix"`
} }
// GetReviewersByPullID gets all reviewers for a pull request with the statuses // GetReviewersByPullID gets all reviewers for a pull request with the statuses

@ -26,7 +26,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
@ -62,8 +62,8 @@ type PublicKey struct {
Type KeyType `xorm:"NOT NULL DEFAULT 1"` Type KeyType `xorm:"NOT NULL DEFAULT 1"`
LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"` LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix util.TimeStamp `xorm:"updated"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
HasRecentActivity bool `xorm:"-"` HasRecentActivity bool `xorm:"-"`
HasUsed bool `xorm:"-"` HasUsed bool `xorm:"-"`
} }
@ -71,7 +71,7 @@ type PublicKey struct {
// AfterLoad is invoked from XORM after setting the values of all fields of this object. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
func (key *PublicKey) AfterLoad() { func (key *PublicKey) AfterLoad() {
key.HasUsed = key.UpdatedUnix > key.CreatedUnix key.HasUsed = key.UpdatedUnix > key.CreatedUnix
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow() key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
} }
// OmitEmail returns content of public key without email address. // OmitEmail returns content of public key without email address.
@ -581,7 +581,7 @@ func UpdatePublicKeyUpdated(id int64) error {
} }
_, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{ _, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{
UpdatedUnix: util.TimeStampNow(), UpdatedUnix: timeutil.TimeStampNow(),
}) })
if err != nil { if err != nil {
return err return err
@ -714,8 +714,8 @@ type DeployKey struct {
Mode AccessMode `xorm:"NOT NULL DEFAULT 1"` Mode AccessMode `xorm:"NOT NULL DEFAULT 1"`
CreatedUnix util.TimeStamp `xorm:"created"` CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix util.TimeStamp `xorm:"updated"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
HasRecentActivity bool `xorm:"-"` HasRecentActivity bool `xorm:"-"`
HasUsed bool `xorm:"-"` HasUsed bool `xorm:"-"`
} }
@ -723,7 +723,7 @@ type DeployKey struct {
// AfterLoad is invoked from XORM after setting the values of all fields of this object. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
func (key *DeployKey) AfterLoad() { func (key *DeployKey) AfterLoad() {
key.HasUsed = key.UpdatedUnix > key.CreatedUnix key.HasUsed = key.UpdatedUnix > key.CreatedUnix
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow() key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
} }
// GetContent gets associated public key content. // GetContent gets associated public key content.

@ -9,11 +9,11 @@ import (
"crypto/subtle" "crypto/subtle"
"time" "time"
gouuid "github.com/satori/go.uuid"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
gouuid "github.com/satori/go.uuid"
) )
// AccessToken represents a personal access token. // AccessToken represents a personal access token.
@ -26,8 +26,8 @@ type AccessToken struct {
TokenSalt string TokenSalt string
TokenLastEight string `xorm:"token_last_eight"` TokenLastEight string `xorm:"token_last_eight"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
HasRecentActivity bool `xorm:"-"` HasRecentActivity bool `xorm:"-"`
HasUsed bool `xorm:"-"` HasUsed bool `xorm:"-"`
} }
@ -35,7 +35,7 @@ type AccessToken struct {
// AfterLoad is invoked from XORM after setting the values of all fields of this object. // AfterLoad is invoked from XORM after setting the values of all fields of this object.
func (t *AccessToken) AfterLoad() { func (t *AccessToken) AfterLoad() {
t.HasUsed = t.UpdatedUnix > t.CreatedUnix t.HasUsed = t.UpdatedUnix > t.CreatedUnix
t.HasRecentActivity = t.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow() t.HasRecentActivity = t.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
} }
// NewAccessToken creates new access token. // NewAccessToken creates new access token.

@ -9,7 +9,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"xorm.io/builder" "xorm.io/builder"
) )
@ -28,8 +28,8 @@ type Topic struct {
ID int64 ID int64
Name string `xorm:"UNIQUE VARCHAR(25)"` Name string `xorm:"UNIQUE VARCHAR(25)"`
RepoCount int RepoCount int
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// RepoTopic represents associated repositories and topics // RepoTopic represents associated repositories and topics

@ -16,12 +16,12 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/pquerna/otp/totp"
"golang.org/x/crypto/pbkdf2"
"code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/pquerna/otp/totp"
"golang.org/x/crypto/pbkdf2"
) )
// TwoFactor represents a two-factor authentication token. // TwoFactor represents a two-factor authentication token.
@ -32,8 +32,8 @@ type TwoFactor struct {
ScratchSalt string ScratchSalt string
ScratchHash string ScratchHash string
LastUsedPasscode string `xorm:"VARCHAR(10)"` LastUsedPasscode string `xorm:"VARCHAR(10)"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// GenerateScratchToken recreates the scratch token the user is using. // GenerateScratchToken recreates the scratch token the user is using.

@ -6,7 +6,7 @@ package models
import ( import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/tstranex/u2f" "github.com/tstranex/u2f"
) )
@ -18,8 +18,8 @@ type U2FRegistration struct {
UserID int64 `xorm:"INDEX"` UserID int64 `xorm:"INDEX"`
Raw []byte Raw []byte
Counter uint32 `xorm:"BIGINT"` Counter uint32 `xorm:"BIGINT"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// TableName returns a better table name for U2FRegistration // TableName returns a better table name for U2FRegistration

@ -11,7 +11,7 @@ import (
"time" "time"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// env keys for git hooks need // env keys for git hooks need
@ -140,7 +140,7 @@ func PushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string)
IsDraft: false, IsDraft: false,
IsPrerelease: false, IsPrerelease: false,
IsTag: true, IsTag: true,
CreatedUnix: util.TimeStamp(createdAt.Unix()), CreatedUnix: timeutil.TimeStamp(createdAt.Unix()),
} }
if author != nil { if author != nil {
rel.PublisherID = author.ID rel.PublisherID = author.ID
@ -151,7 +151,7 @@ func PushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string)
} }
} else { } else {
rel.Sha1 = commit.ID.String() rel.Sha1 = commit.ID.String()
rel.CreatedUnix = util.TimeStamp(createdAt.Unix()) rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix())
rel.NumCommits = commitsCount rel.NumCommits = commitsCount
rel.IsDraft = false rel.IsDraft = false
if rel.IsTag && author != nil { if rel.IsTag && author != nil {

@ -29,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/Unknwon/com" "github.com/Unknwon/com"
@ -110,9 +111,9 @@ type User struct {
Language string `xorm:"VARCHAR(5)"` Language string `xorm:"VARCHAR(5)"`
Description string Description string
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
LastLoginUnix util.TimeStamp `xorm:"INDEX"` LastLoginUnix timeutil.TimeStamp `xorm:"INDEX"`
// Remember visibility choice for convenience, true for private // Remember visibility choice for convenience, true for private
LastRepoVisibility bool LastRepoVisibility bool
@ -190,7 +191,7 @@ func (u *User) AfterLoad() {
// SetLastLogin set time to last login // SetLastLogin set time to last login
func (u *User) SetLastLogin() { func (u *User) SetLastLogin() {
u.LastLoginUnix = util.TimeStampNow() u.LastLoginUnix = timeutil.TimeStampNow()
} }
// UpdateDiffViewStyle updates the users diff view style // UpdateDiffViewStyle updates the users diff view style

@ -6,12 +6,12 @@ package models
import ( import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// UserHeatmapData represents the data needed to create a heatmap // UserHeatmapData represents the data needed to create a heatmap
type UserHeatmapData struct { type UserHeatmapData struct {
Timestamp util.TimeStamp `json:"timestamp"` Timestamp timeutil.TimeStamp `json:"timestamp"`
Contributions int64 `json:"contributions"` Contributions int64 `json:"contributions"`
} }
@ -35,7 +35,7 @@ func GetUserHeatmapDataByUser(user *User) ([]*UserHeatmapData, error) {
sess := x.Select(groupBy+" AS timestamp, count(user_id) as contributions"). sess := x.Select(groupBy+" AS timestamp, count(user_id) as contributions").
Table("action"). Table("action").
Where("user_id = ?", user.ID). Where("user_id = ?", user.ID).
And("created_unix > ?", (util.TimeStampNow() - 31536000)) And("created_unix > ?", (timeutil.TimeStampNow() - 31536000))
// * Heatmaps for individual users only include actions that the user themself // * Heatmaps for individual users only include actions that the user themself
// did. // did.

@ -23,7 +23,8 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/sync" "code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/Unknwon/com" "github.com/Unknwon/com"
gouuid "github.com/satori/go.uuid" gouuid "github.com/satori/go.uuid"
) )
@ -118,8 +119,8 @@ type Webhook struct {
Meta string `xorm:"TEXT"` // store hook-specific attributes Meta string `xorm:"TEXT"` // store hook-specific attributes
LastStatus HookStatus // Last delivery status LastStatus HookStatus // Last delivery status
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
} }
// AfterLoad updates the webhook object upon setting a column // AfterLoad updates the webhook object upon setting a column

@ -20,7 +20,7 @@ import (
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/validation"
) )
@ -68,7 +68,7 @@ func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
} }
return 0 return 0
} }
t.UpdatedUnix = util.TimeStampNow() t.UpdatedUnix = timeutil.TimeStampNow()
if err = models.UpdateAccessToken(t); err != nil { if err = models.UpdateAccessToken(t); err != nil {
log.Error("UpdateAccessToken: %v", err) log.Error("UpdateAccessToken: %v", err)
} }
@ -210,7 +210,7 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool)
return nil, false return nil, false
} }
} }
token.UpdatedUnix = util.TimeStampNow() token.UpdatedUnix = timeutil.TimeStampNow()
if err = models.UpdateAccessToken(token); err != nil { if err = models.UpdateAccessToken(token); err != nil {
log.Error("UpdateAccessToken: %v", err) log.Error("UpdateAccessToken: %v", err)
} }

@ -12,7 +12,6 @@ import (
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"html/template"
"io" "io"
"math" "math"
"net/http" "net/http"
@ -29,10 +28,8 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/Unknwon/i18n"
) )
// EncodeMD5 encodes string to md5 hex value. // EncodeMD5 encodes string to md5 hex value.
@ -217,154 +214,6 @@ func AvatarLink(email string) string {
return SizedAvatarLink(email, DefaultAvatarSize) return SizedAvatarLink(email, DefaultAvatarSize)
} }
// Seconds-based time units
const (
Minute = 60
Hour = 60 * Minute
Day = 24 * Hour
Week = 7 * Day
Month = 30 * Day
Year = 12 * Month
)
func computeTimeDiff(diff int64, lang string) (int64, string) {
diffStr := ""
switch {
case diff <= 0:
diff = 0
diffStr = i18n.Tr(lang, "tool.now")
case diff < 2:
diff = 0
diffStr = i18n.Tr(lang, "tool.1s")
case diff < 1*Minute:
diffStr = i18n.Tr(lang, "tool.seconds", diff)
diff = 0
case diff < 2*Minute:
diff -= 1 * Minute
diffStr = i18n.Tr(lang, "tool.1m")
case diff < 1*Hour:
diffStr = i18n.Tr(lang, "tool.minutes", diff/Minute)
diff -= diff / Minute * Minute
case diff < 2*Hour:
diff -= 1 * Hour
diffStr = i18n.Tr(lang, "tool.1h")
case diff < 1*Day:
diffStr = i18n.Tr(lang, "tool.hours", diff/Hour)
diff -= diff / Hour * Hour
case diff < 2*Day:
diff -= 1 * Day
diffStr = i18n.Tr(lang, "tool.1d")
case diff < 1*Week:
diffStr = i18n.Tr(lang, "tool.days", diff/Day)
diff -= diff / Day * Day
case diff < 2*Week:
diff -= 1 * Week
diffStr = i18n.Tr(lang, "tool.1w")
case diff < 1*Month:
diffStr = i18n.Tr(lang, "tool.weeks", diff/Week)
diff -= diff / Week * Week
case diff < 2*Month:
diff -= 1 * Month
diffStr = i18n.Tr(lang, "tool.1mon")
case diff < 1*Year:
diffStr = i18n.Tr(lang, "tool.months", diff/Month)
diff -= diff / Month * Month
case diff < 2*Year:
diff -= 1 * Year
diffStr = i18n.Tr(lang, "tool.1y")
default:
diffStr = i18n.Tr(lang, "tool.years", diff/Year)
diff -= (diff / Year) * Year
}
return diff, diffStr
}
// MinutesToFriendly returns a user friendly string with number of minutes
// converted to hours and minutes.
func MinutesToFriendly(minutes int, lang string) string {
duration := time.Duration(minutes) * time.Minute
return TimeSincePro(time.Now().Add(-duration), lang)
}
// TimeSincePro calculates the time interval and generate full user-friendly string.
func TimeSincePro(then time.Time, lang string) string {
return timeSincePro(then, time.Now(), lang)
}
func timeSincePro(then, now time.Time, lang string) string {
diff := now.Unix() - then.Unix()
if then.After(now) {
return i18n.Tr(lang, "tool.future")
}
if diff == 0 {
return i18n.Tr(lang, "tool.now")
}
var timeStr, diffStr string
for {
if diff == 0 {
break
}
diff, diffStr = computeTimeDiff(diff, lang)
timeStr += ", " + diffStr
}
return strings.TrimPrefix(timeStr, ", ")
}
func timeSince(then, now time.Time, lang string) string {
return timeSinceUnix(then.Unix(), now.Unix(), lang)
}
func timeSinceUnix(then, now int64, lang string) string {
lbl := "tool.ago"
diff := now - then
if then > now {
lbl = "tool.from_now"
diff = then - now
}
if diff <= 0 {
return i18n.Tr(lang, "tool.now")
}
_, diffStr := computeTimeDiff(diff, lang)
return i18n.Tr(lang, lbl, diffStr)
}
// RawTimeSince retrieves i18n key of time since t
func RawTimeSince(t time.Time, lang string) string {
return timeSince(t, time.Now(), lang)
}
// TimeSince calculates the time interval and generate user-friendly string.
func TimeSince(then time.Time, lang string) template.HTML {
return htmlTimeSince(then, time.Now(), lang)
}
func htmlTimeSince(then, now time.Time, lang string) template.HTML {
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`,
then.Format(setting.TimeFormat),
timeSince(then, now, lang)))
}
// TimeSinceUnix calculates the time interval and generate user-friendly string.
func TimeSinceUnix(then util.TimeStamp, lang string) template.HTML {
return htmlTimeSinceUnix(then, util.TimeStamp(time.Now().Unix()), lang)
}
func htmlTimeSinceUnix(then, now util.TimeStamp, lang string) template.HTML {
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`,
then.Format(setting.TimeFormat),
timeSinceUnix(int64(then), int64(now), lang)))
}
// Storage space size types // Storage space size types
const ( const (
Byte = 1 Byte = 1

@ -2,43 +2,13 @@ package base
import ( import (
"net/url" "net/url"
"os"
"testing" "testing"
"time"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"github.com/Unknwon/i18n"
macaroni18n "github.com/go-macaron/i18n"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
var BaseDate time.Time
// time durations
const (
DayDur = 24 * time.Hour
WeekDur = 7 * DayDur
MonthDur = 30 * DayDur
YearDur = 12 * MonthDur
)
func TestMain(m *testing.M) {
// setup
macaroni18n.I18n(macaroni18n.Options{
Directory: "../../options/locale/",
DefaultLang: "en-US",
Langs: []string{"en-US"},
Names: []string{"english"},
})
BaseDate = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
// run the tests
retVal := m.Run()
os.Exit(retVal)
}
func TestEncodeMD5(t *testing.T) { func TestEncodeMD5(t *testing.T) {
assert.Equal(t, assert.Equal(t,
"3858f62230ac3c915f300c664312c63f", "3858f62230ac3c915f300c664312c63f",
@ -131,125 +101,6 @@ func TestAvatarLink(t *testing.T) {
) )
} }
func TestComputeTimeDiff(t *testing.T) {
// test that for each offset in offsets,
// computeTimeDiff(base + offset) == (offset, str)
test := func(base int64, str string, offsets ...int64) {
for _, offset := range offsets {
diff, diffStr := computeTimeDiff(base+offset, "en")
assert.Equal(t, offset, diff)
assert.Equal(t, str, diffStr)
}
}
test(0, "now", 0)
test(1, "1 second", 0)
test(2, "2 seconds", 0)
test(Minute, "1 minute", 0, 1, 30, Minute-1)
test(2*Minute, "2 minutes", 0, Minute-1)
test(Hour, "1 hour", 0, 1, Hour-1)
test(5*Hour, "5 hours", 0, Hour-1)
test(Day, "1 day", 0, 1, Day-1)
test(5*Day, "5 days", 0, Day-1)
test(Week, "1 week", 0, 1, Week-1)
test(3*Week, "3 weeks", 0, 4*Day+25000)
test(Month, "1 month", 0, 1, Month-1)
test(10*Month, "10 months", 0, Month-1)
test(Year, "1 year", 0, Year-1)
test(3*Year, "3 years", 0, Year-1)
}
func TestMinutesToFriendly(t *testing.T) {
// test that a number of minutes yields the expected string
test := func(expected string, minutes int) {
actual := MinutesToFriendly(minutes, "en")
assert.Equal(t, expected, actual)
}
test("1 minute", 1)
test("2 minutes", 2)
test("1 hour", 60)
test("1 hour, 1 minute", 61)
test("1 hour, 2 minutes", 62)
test("2 hours", 120)
}
func TestTimeSince(t *testing.T) {
assert.Equal(t, "now", timeSince(BaseDate, BaseDate, "en"))
// test that each diff in `diffs` yields the expected string
test := func(expected string, diffs ...time.Duration) {
for _, diff := range diffs {
actual := timeSince(BaseDate, BaseDate.Add(diff), "en")
assert.Equal(t, i18n.Tr("en", "tool.ago", expected), actual)
actual = timeSince(BaseDate.Add(diff), BaseDate, "en")
assert.Equal(t, i18n.Tr("en", "tool.from_now", expected), actual)
}
}
test("1 second", time.Second, time.Second+50*time.Millisecond)
test("2 seconds", 2*time.Second, 2*time.Second+50*time.Millisecond)
test("1 minute", time.Minute, time.Minute+30*time.Second)
test("2 minutes", 2*time.Minute, 2*time.Minute+30*time.Second)
test("1 hour", time.Hour, time.Hour+30*time.Minute)
test("2 hours", 2*time.Hour, 2*time.Hour+30*time.Minute)
test("1 day", DayDur, DayDur+12*time.Hour)
test("2 days", 2*DayDur, 2*DayDur+12*time.Hour)
test("1 week", WeekDur, WeekDur+3*DayDur)
test("2 weeks", 2*WeekDur, 2*WeekDur+3*DayDur)
test("1 month", MonthDur, MonthDur+15*DayDur)
test("2 months", 2*MonthDur, 2*MonthDur+15*DayDur)
test("1 year", YearDur, YearDur+6*MonthDur)
test("2 years", 2*YearDur, 2*YearDur+6*MonthDur)
}
func TestTimeSincePro(t *testing.T) {
assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate, "en"))
// test that a difference of `diff` yields the expected string
test := func(expected string, diff time.Duration) {
actual := timeSincePro(BaseDate, BaseDate.Add(diff), "en")
assert.Equal(t, expected, actual)
assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate, "en"))
}
test("1 second", time.Second)
test("2 seconds", 2*time.Second)
test("1 minute", time.Minute)
test("1 minute, 1 second", time.Minute+time.Second)
test("1 minute, 59 seconds", time.Minute+59*time.Second)
test("2 minutes", 2*time.Minute)
test("1 hour", time.Hour)
test("1 hour, 1 second", time.Hour+time.Second)
test("1 hour, 59 minutes, 59 seconds", time.Hour+59*time.Minute+59*time.Second)
test("2 hours", 2*time.Hour)
test("1 day", DayDur)
test("1 day, 23 hours, 59 minutes, 59 seconds",
DayDur+23*time.Hour+59*time.Minute+59*time.Second)
test("2 days", 2*DayDur)
test("1 week", WeekDur)
test("2 weeks", 2*WeekDur)
test("1 month", MonthDur)
test("3 months", 3*MonthDur)
test("1 year", YearDur)
test("2 years, 3 months, 1 week, 2 days, 4 hours, 12 minutes, 17 seconds",
2*YearDur+3*MonthDur+WeekDur+2*DayDur+4*time.Hour+
12*time.Minute+17*time.Second)
}
func TestHtmlTimeSince(t *testing.T) {
setting.TimeFormat = time.UnixDate
// test that `diff` yields a result containing `expected`
test := func(expected string, diff time.Duration) {
actual := htmlTimeSince(BaseDate, BaseDate.Add(diff), "en")
assert.Contains(t, actual, `title="Sat Jan 1 00:00:00 UTC 2000"`)
assert.Contains(t, actual, expected)
}
test("1 second", time.Second)
test("3 minutes", 3*time.Minute+5*time.Second)
test("1 day", DayDur+18*time.Hour)
test("1 week", WeekDur+6*DayDur)
test("3 months", 3*MonthDur+3*WeekDur)
test("2 years", 2*YearDur)
test("3 years", 3*YearDur+11*MonthDur+4*WeekDur)
}
func TestFileSize(t *testing.T) { func TestFileSize(t *testing.T) {
var size int64 = 512 var size int64 = 512
assert.Equal(t, "512B", FileSize(size)) assert.Equal(t, "512B", FileSize(size))

@ -21,7 +21,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/migrations/base" "code.gitea.io/gitea/modules/migrations/base"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
gouuid "github.com/satori/go.uuid" gouuid "github.com/satori/go.uuid"
) )
@ -106,12 +106,12 @@ func (g *GiteaLocalUploader) CreateTopics(topics ...string) error {
func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) error { func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) error {
var mss = make([]*models.Milestone, 0, len(milestones)) var mss = make([]*models.Milestone, 0, len(milestones))
for _, milestone := range milestones { for _, milestone := range milestones {
var deadline util.TimeStamp var deadline timeutil.TimeStamp
if milestone.Deadline != nil { if milestone.Deadline != nil {
deadline = util.TimeStamp(milestone.Deadline.Unix()) deadline = timeutil.TimeStamp(milestone.Deadline.Unix())
} }
if deadline == 0 { if deadline == 0 {
deadline = util.TimeStamp(time.Date(9999, 1, 1, 0, 0, 0, 0, setting.UILocation).Unix()) deadline = timeutil.TimeStamp(time.Date(9999, 1, 1, 0, 0, 0, 0, setting.DefaultUILocation).Unix())
} }
var ms = models.Milestone{ var ms = models.Milestone{
RepoID: g.repo.ID, RepoID: g.repo.ID,
@ -121,7 +121,7 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err
DeadlineUnix: deadline, DeadlineUnix: deadline,
} }
if ms.IsClosed && milestone.Closed != nil { if ms.IsClosed && milestone.Closed != nil {
ms.ClosedDateUnix = util.TimeStamp(milestone.Closed.Unix()) ms.ClosedDateUnix = timeutil.TimeStamp(milestone.Closed.Unix())
} }
mss = append(mss, &ms) mss = append(mss, &ms)
} }
@ -175,7 +175,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
IsDraft: release.Draft, IsDraft: release.Draft,
IsPrerelease: release.Prerelease, IsPrerelease: release.Prerelease,
IsTag: false, IsTag: false,
CreatedUnix: util.TimeStamp(release.Created.Unix()), CreatedUnix: timeutil.TimeStamp(release.Created.Unix()),
} }
// calc NumCommits // calc NumCommits
@ -194,7 +194,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
Name: asset.Name, Name: asset.Name,
DownloadCount: int64(*asset.DownloadCount), DownloadCount: int64(*asset.DownloadCount),
Size: int64(*asset.Size), Size: int64(*asset.Size),
CreatedUnix: util.TimeStamp(asset.Created.Unix()), CreatedUnix: timeutil.TimeStamp(asset.Created.Unix()),
} }
// download attachment // download attachment
@ -265,10 +265,10 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error {
IsLocked: issue.IsLocked, IsLocked: issue.IsLocked,
MilestoneID: milestoneID, MilestoneID: milestoneID,
Labels: labels, Labels: labels,
CreatedUnix: util.TimeStamp(issue.Created.Unix()), CreatedUnix: timeutil.TimeStamp(issue.Created.Unix()),
} }
if issue.Closed != nil { if issue.Closed != nil {
is.ClosedUnix = util.TimeStamp(issue.Closed.Unix()) is.ClosedUnix = timeutil.TimeStamp(issue.Closed.Unix())
} }
// TODO: add reactions // TODO: add reactions
iss = append(iss, &is) iss = append(iss, &is)
@ -307,7 +307,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
OriginalAuthor: comment.PosterName, OriginalAuthor: comment.PosterName,
OriginalAuthorID: comment.PosterID, OriginalAuthorID: comment.PosterID,
Content: comment.Content, Content: comment.Content,
CreatedUnix: util.TimeStamp(comment.Created.Unix()), CreatedUnix: timeutil.TimeStamp(comment.Created.Unix()),
}) })
// TODO: Reactions // TODO: Reactions
@ -453,15 +453,15 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
IsClosed: pr.State == "closed", IsClosed: pr.State == "closed",
IsLocked: pr.IsLocked, IsLocked: pr.IsLocked,
Labels: labels, Labels: labels,
CreatedUnix: util.TimeStamp(pr.Created.Unix()), CreatedUnix: timeutil.TimeStamp(pr.Created.Unix()),
}, },
} }
if pullRequest.Issue.IsClosed && pr.Closed != nil { if pullRequest.Issue.IsClosed && pr.Closed != nil {
pullRequest.Issue.ClosedUnix = util.TimeStamp(pr.Closed.Unix()) pullRequest.Issue.ClosedUnix = timeutil.TimeStamp(pr.Closed.Unix())
} }
if pullRequest.HasMerged && pr.MergedTime != nil { if pullRequest.HasMerged && pr.MergedTime != nil {
pullRequest.MergedUnix = util.TimeStamp(pr.MergedTime.Unix()) pullRequest.MergedUnix = timeutil.TimeStamp(pr.MergedTime.Unix())
pullRequest.MergedCommitID = pr.MergeCommitSHA pullRequest.MergedCommitID = pr.MergeCommitSHA
pullRequest.MergerID = g.doer.ID pullRequest.MergerID = g.doer.ID
} }

@ -21,7 +21,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// Merge merges pull request to base repository. // Merge merges pull request to base repository.
@ -258,7 +258,7 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
return fmt.Errorf("GetBranchCommit: %v", err) return fmt.Errorf("GetBranchCommit: %v", err)
} }
pr.MergedUnix = util.TimeStampNow() pr.MergedUnix = timeutil.TimeStampNow()
pr.Merger = doer pr.Merger = doer
pr.MergerID = doer.ID pr.MergerID = doer.ID

@ -278,6 +278,8 @@ var (
// Time settings // Time settings
TimeFormat string TimeFormat string
// UILocation is the location on the UI, so that we can display the time on UI.
DefaultUILocation = time.Local
CSRFCookieName = "_csrf" CSRFCookieName = "_csrf"
CSRFCookieHTTPOnly = true CSRFCookieHTTPOnly = true
@ -356,10 +358,6 @@ var (
HasRobotsTxt bool HasRobotsTxt bool
InternalToken string // internal access token InternalToken string // internal access token
IterateBufferSize int IterateBufferSize int
// UILocation is the location on the UI, so that we can display the time on UI.
// Currently only show the default time.Local, it could be added to app.ini after UI is ready
UILocation = time.Local
) )
// DateLang transforms standard language locale name to corresponding value in datetime plugin. // DateLang transforms standard language locale name to corresponding value in datetime plugin.
@ -792,7 +790,8 @@ func NewContext() {
AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5) AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5)
AttachmentEnabled = sec.Key("ENABLED").MustBool(true) AttachmentEnabled = sec.Key("ENABLED").MustBool(true)
TimeFormatKey := Cfg.Section("time").Key("FORMAT").MustString("RFC1123") timeFormatKey := Cfg.Section("time").Key("FORMAT").MustString("")
if timeFormatKey != "" {
TimeFormat = map[string]string{ TimeFormat = map[string]string{
"ANSIC": time.ANSIC, "ANSIC": time.ANSIC,
"UnixDate": time.UnixDate, "UnixDate": time.UnixDate,
@ -809,16 +808,30 @@ func NewContext() {
"StampMilli": time.StampMilli, "StampMilli": time.StampMilli,
"StampMicro": time.StampMicro, "StampMicro": time.StampMicro,
"StampNano": time.StampNano, "StampNano": time.StampNano,
}[TimeFormatKey] }[timeFormatKey]
// When the TimeFormatKey does not exist in the previous map e.g.'2006-01-02 15:04:05' // When the TimeFormatKey does not exist in the previous map e.g.'2006-01-02 15:04:05'
if len(TimeFormat) == 0 { if len(TimeFormat) == 0 {
TimeFormat = TimeFormatKey TimeFormat = timeFormatKey
TestTimeFormat, _ := time.Parse(TimeFormat, TimeFormat) TestTimeFormat, _ := time.Parse(TimeFormat, TimeFormat)
if TestTimeFormat.Format(time.RFC3339) != "2006-01-02T15:04:05Z" { if TestTimeFormat.Format(time.RFC3339) != "2006-01-02T15:04:05Z" {
log.Fatal("Can't create time properly, please check your time format has 2006, 01, 02, 15, 04 and 05") log.Fatal("Can't create time properly, please check your time format has 2006, 01, 02, 15, 04 and 05")
} }
log.Trace("Custom TimeFormat: %s", TimeFormat) log.Trace("Custom TimeFormat: %s", TimeFormat)
} }
}
zone := Cfg.Section("time").Key("DEFAULT_UI_LOCATION").String()
if zone != "" {
DefaultUILocation, err = time.LoadLocation(zone)
if err != nil {
log.Fatal("Load time zone failed: %v", err)
} else {
log.Info("Default UI Location is %v", zone)
}
}
if DefaultUILocation == nil {
DefaultUILocation = time.Local
}
RunUser = Cfg.Section("").Key("RUN_USER").MustString(user.CurrentUsername()) RunUser = Cfg.Section("").Key("RUN_USER").MustString(user.CurrentUsername())
// Does not check run user when the install lock is off. // Does not check run user when the install lock is off.

@ -20,13 +20,13 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"gopkg.in/editorconfig/editorconfig-core-go.v1" "gopkg.in/editorconfig/editorconfig-core-go.v1"
) )
@ -74,9 +74,9 @@ func NewFuncMap() []template.FuncMap {
"Safe": Safe, "Safe": Safe,
"SafeJS": SafeJS, "SafeJS": SafeJS,
"Str2html": Str2html, "Str2html": Str2html,
"TimeSince": base.TimeSince, "TimeSince": timeutil.TimeSince,
"TimeSinceUnix": base.TimeSinceUnix, "TimeSinceUnix": timeutil.TimeSinceUnix,
"RawTimeSince": base.RawTimeSince, "RawTimeSince": timeutil.RawTimeSince,
"FileSize": base.FileSize, "FileSize": base.FileSize,
"Subtract": base.Subtract, "Subtract": base.Subtract,
"EntryIcon": base.EntryIcon, "EntryIcon": base.EntryIcon,

@ -0,0 +1,36 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package timeutil
import (
"time"
"code.gitea.io/gitea/modules/setting"
)
var (
langTimeFormats = map[string]string{
"zh-CN": "2006年01月02日 15时04分05秒",
"en-US": time.RFC1123,
"lv-LV": "02.01.2006. 15:04:05",
}
)
// GetLangTimeFormat represents the default time format for the language
func GetLangTimeFormat(lang string) string {
return langTimeFormats[lang]
}
// GetTimeFormat represents the
func GetTimeFormat(lang string) string {
if setting.TimeFormat == "" {
format := GetLangTimeFormat(lang)
if format == "" {
format = time.RFC1123
}
return format
}
return setting.TimeFormat
}

@ -0,0 +1,164 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package timeutil
import (
"fmt"
"html/template"
"strings"
"time"
"code.gitea.io/gitea/modules/setting"
"github.com/Unknwon/i18n"
)
// Seconds-based time units
const (
Minute = 60
Hour = 60 * Minute
Day = 24 * Hour
Week = 7 * Day
Month = 30 * Day
Year = 12 * Month
)
func computeTimeDiff(diff int64, lang string) (int64, string) {
diffStr := ""
switch {
case diff <= 0:
diff = 0
diffStr = i18n.Tr(lang, "tool.now")
case diff < 2:
diff = 0
diffStr = i18n.Tr(lang, "tool.1s")
case diff < 1*Minute:
diffStr = i18n.Tr(lang, "tool.seconds", diff)
diff = 0
case diff < 2*Minute:
diff -= 1 * Minute
diffStr = i18n.Tr(lang, "tool.1m")
case diff < 1*Hour:
diffStr = i18n.Tr(lang, "tool.minutes", diff/Minute)
diff -= diff / Minute * Minute
case diff < 2*Hour:
diff -= 1 * Hour
diffStr = i18n.Tr(lang, "tool.1h")
case diff < 1*Day:
diffStr = i18n.Tr(lang, "tool.hours", diff/Hour)
diff -= diff / Hour * Hour
case diff < 2*Day:
diff -= 1 * Day
diffStr = i18n.Tr(lang, "tool.1d")
case diff < 1*Week:
diffStr = i18n.Tr(lang, "tool.days", diff/Day)
diff -= diff / Day * Day
case diff < 2*Week:
diff -= 1 * Week
diffStr = i18n.Tr(lang, "tool.1w")
case diff < 1*Month:
diffStr = i18n.Tr(lang, "tool.weeks", diff/Week)
diff -= diff / Week * Week
case diff < 2*Month:
diff -= 1 * Month
diffStr = i18n.Tr(lang, "tool.1mon")
case diff < 1*Year:
diffStr = i18n.Tr(lang, "tool.months", diff/Month)
diff -= diff / Month * Month
case diff < 2*Year:
diff -= 1 * Year
diffStr = i18n.Tr(lang, "tool.1y")
default:
diffStr = i18n.Tr(lang, "tool.years", diff/Year)
diff -= (diff / Year) * Year
}
return diff, diffStr
}
// MinutesToFriendly returns a user friendly string with number of minutes
// converted to hours and minutes.
func MinutesToFriendly(minutes int, lang string) string {
duration := time.Duration(minutes) * time.Minute
return TimeSincePro(time.Now().Add(-duration), lang)
}
// TimeSincePro calculates the time interval and generate full user-friendly string.
func TimeSincePro(then time.Time, lang string) string {
return timeSincePro(then, time.Now(), lang)
}
func timeSincePro(then, now time.Time, lang string) string {
diff := now.Unix() - then.Unix()
if then.After(now) {
return i18n.Tr(lang, "tool.future")
}
if diff == 0 {
return i18n.Tr(lang, "tool.now")
}
var timeStr, diffStr string
for {
if diff == 0 {
break
}
diff, diffStr = computeTimeDiff(diff, lang)
timeStr += ", " + diffStr
}
return strings.TrimPrefix(timeStr, ", ")
}
func timeSince(then, now time.Time, lang string) string {
return timeSinceUnix(then.Unix(), now.Unix(), lang)
}
func timeSinceUnix(then, now int64, lang string) string {
lbl := "tool.ago"
diff := now - then
if then > now {
lbl = "tool.from_now"
diff = then - now
}
if diff <= 0 {
return i18n.Tr(lang, "tool.now")
}
_, diffStr := computeTimeDiff(diff, lang)
return i18n.Tr(lang, lbl, diffStr)
}
// RawTimeSince retrieves i18n key of time since t
func RawTimeSince(t time.Time, lang string) string {
return timeSince(t, time.Now(), lang)
}
// TimeSince calculates the time interval and generate user-friendly string.
func TimeSince(then time.Time, lang string) template.HTML {
return htmlTimeSince(then, time.Now(), lang)
}
func htmlTimeSince(then, now time.Time, lang string) template.HTML {
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`,
then.In(setting.DefaultUILocation).Format(GetTimeFormat(lang)),
timeSince(then, now, lang)))
}
// TimeSinceUnix calculates the time interval and generate user-friendly string.
func TimeSinceUnix(then TimeStamp, lang string) template.HTML {
return htmlTimeSinceUnix(then, TimeStamp(time.Now().Unix()), lang)
}
func htmlTimeSinceUnix(then, now TimeStamp, lang string) template.HTML {
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`,
then.FormatInLocation(GetTimeFormat(lang), setting.DefaultUILocation),
timeSinceUnix(int64(then), int64(now), lang)))
}

@ -0,0 +1,163 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package timeutil
import (
"os"
"testing"
"time"
"code.gitea.io/gitea/modules/setting"
"github.com/Unknwon/i18n"
macaroni18n "github.com/go-macaron/i18n"
"github.com/stretchr/testify/assert"
)
var BaseDate time.Time
// time durations
const (
DayDur = 24 * time.Hour
WeekDur = 7 * DayDur
MonthDur = 30 * DayDur
YearDur = 12 * MonthDur
)
func TestMain(m *testing.M) {
// setup
macaroni18n.I18n(macaroni18n.Options{
Directory: "../../options/locale/",
DefaultLang: "en-US",
Langs: []string{"en-US"},
Names: []string{"english"},
})
BaseDate = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
// run the tests
retVal := m.Run()
os.Exit(retVal)
}
func TestTimeSince(t *testing.T) {
assert.Equal(t, "now", timeSince(BaseDate, BaseDate, "en"))
// test that each diff in `diffs` yields the expected string
test := func(expected string, diffs ...time.Duration) {
for _, diff := range diffs {
actual := timeSince(BaseDate, BaseDate.Add(diff), "en")
assert.Equal(t, i18n.Tr("en", "tool.ago", expected), actual)
actual = timeSince(BaseDate.Add(diff), BaseDate, "en")
assert.Equal(t, i18n.Tr("en", "tool.from_now", expected), actual)
}
}
test("1 second", time.Second, time.Second+50*time.Millisecond)
test("2 seconds", 2*time.Second, 2*time.Second+50*time.Millisecond)
test("1 minute", time.Minute, time.Minute+30*time.Second)
test("2 minutes", 2*time.Minute, 2*time.Minute+30*time.Second)
test("1 hour", time.Hour, time.Hour+30*time.Minute)
test("2 hours", 2*time.Hour, 2*time.Hour+30*time.Minute)
test("1 day", DayDur, DayDur+12*time.Hour)
test("2 days", 2*DayDur, 2*DayDur+12*time.Hour)
test("1 week", WeekDur, WeekDur+3*DayDur)
test("2 weeks", 2*WeekDur, 2*WeekDur+3*DayDur)
test("1 month", MonthDur, MonthDur+15*DayDur)
test("2 months", 2*MonthDur, 2*MonthDur+15*DayDur)
test("1 year", YearDur, YearDur+6*MonthDur)
test("2 years", 2*YearDur, 2*YearDur+6*MonthDur)
}
func TestTimeSincePro(t *testing.T) {
assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate, "en"))
// test that a difference of `diff` yields the expected string
test := func(expected string, diff time.Duration) {
actual := timeSincePro(BaseDate, BaseDate.Add(diff), "en")
assert.Equal(t, expected, actual)
assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate, "en"))
}
test("1 second", time.Second)
test("2 seconds", 2*time.Second)
test("1 minute", time.Minute)
test("1 minute, 1 second", time.Minute+time.Second)
test("1 minute, 59 seconds", time.Minute+59*time.Second)
test("2 minutes", 2*time.Minute)
test("1 hour", time.Hour)
test("1 hour, 1 second", time.Hour+time.Second)
test("1 hour, 59 minutes, 59 seconds", time.Hour+59*time.Minute+59*time.Second)
test("2 hours", 2*time.Hour)
test("1 day", DayDur)
test("1 day, 23 hours, 59 minutes, 59 seconds",
DayDur+23*time.Hour+59*time.Minute+59*time.Second)
test("2 days", 2*DayDur)
test("1 week", WeekDur)
test("2 weeks", 2*WeekDur)
test("1 month", MonthDur)
test("3 months", 3*MonthDur)
test("1 year", YearDur)
test("2 years, 3 months, 1 week, 2 days, 4 hours, 12 minutes, 17 seconds",
2*YearDur+3*MonthDur+WeekDur+2*DayDur+4*time.Hour+
12*time.Minute+17*time.Second)
}
func TestHtmlTimeSince(t *testing.T) {
setting.TimeFormat = time.UnixDate
setting.DefaultUILocation = time.UTC
// test that `diff` yields a result containing `expected`
test := func(expected string, diff time.Duration) {
actual := htmlTimeSince(BaseDate, BaseDate.Add(diff), "en")
assert.Contains(t, actual, `title="Sat Jan 1 00:00:00 UTC 2000"`)
assert.Contains(t, actual, expected)
}
test("1 second", time.Second)
test("3 minutes", 3*time.Minute+5*time.Second)
test("1 day", DayDur+18*time.Hour)
test("1 week", WeekDur+6*DayDur)
test("3 months", 3*MonthDur+3*WeekDur)
test("2 years", 2*YearDur)
test("3 years", 3*YearDur+11*MonthDur+4*WeekDur)
}
func TestComputeTimeDiff(t *testing.T) {
// test that for each offset in offsets,
// computeTimeDiff(base + offset) == (offset, str)
test := func(base int64, str string, offsets ...int64) {
for _, offset := range offsets {
diff, diffStr := computeTimeDiff(base+offset, "en")
assert.Equal(t, offset, diff)
assert.Equal(t, str, diffStr)
}
}
test(0, "now", 0)
test(1, "1 second", 0)
test(2, "2 seconds", 0)
test(Minute, "1 minute", 0, 1, 30, Minute-1)
test(2*Minute, "2 minutes", 0, Minute-1)
test(Hour, "1 hour", 0, 1, Hour-1)
test(5*Hour, "5 hours", 0, Hour-1)
test(Day, "1 day", 0, 1, Day-1)
test(5*Day, "5 days", 0, Day-1)
test(Week, "1 week", 0, 1, Week-1)
test(3*Week, "3 weeks", 0, 4*Day+25000)
test(Month, "1 month", 0, 1, Month-1)
test(10*Month, "10 months", 0, Month-1)
test(Year, "1 year", 0, Year-1)
test(3*Year, "3 years", 0, Year-1)
}
func TestMinutesToFriendly(t *testing.T) {
// test that a number of minutes yields the expected string
test := func(expected string, minutes int) {
actual := MinutesToFriendly(minutes, "en")
assert.Equal(t, expected, actual)
}
test("1 minute", 1)
test("2 minutes", 2)
test("1 hour", 60)
test("1 hour, 1 minute", 61)
test("1 hour, 2 minutes", 62)
test("2 hours", 120)
}

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package util package timeutil
import ( import (
"time" "time"
@ -35,19 +35,34 @@ func (ts TimeStamp) Year() int {
// AsTime convert timestamp as time.Time in Local locale // AsTime convert timestamp as time.Time in Local locale
func (ts TimeStamp) AsTime() (tm time.Time) { func (ts TimeStamp) AsTime() (tm time.Time) {
tm = time.Unix(int64(ts), 0).In(setting.UILocation) return ts.AsTimeInLocation(setting.DefaultUILocation)
}
// AsTimeInLocation convert timestamp as time.Time in Local locale
func (ts TimeStamp) AsTimeInLocation(loc *time.Location) (tm time.Time) {
tm = time.Unix(int64(ts), 0).In(loc)
return return
} }
// AsTimePtr convert timestamp as *time.Time in Local locale // AsTimePtr convert timestamp as *time.Time in Local locale
func (ts TimeStamp) AsTimePtr() *time.Time { func (ts TimeStamp) AsTimePtr() *time.Time {
tm := time.Unix(int64(ts), 0).In(setting.UILocation) return ts.AsTimePtrInLocation(setting.DefaultUILocation)
}
// AsTimePtrInLocation convert timestamp as *time.Time in customize location
func (ts TimeStamp) AsTimePtrInLocation(loc *time.Location) *time.Time {
tm := time.Unix(int64(ts), 0).In(loc)
return &tm return &tm
} }
// Format formats timestamp as // Format formats timestamp as given format
func (ts TimeStamp) Format(f string) string { func (ts TimeStamp) Format(f string) string {
return ts.AsTime().Format(f) return ts.FormatInLocation(f, setting.DefaultUILocation)
}
// FormatInLocation formats timestamp as given format with spiecific location
func (ts TimeStamp) FormatInLocation(f string, loc *time.Location) string {
return ts.AsTimeInLocation(loc).Format(f)
} }
// FormatLong formats as RFC1123Z // FormatLong formats as RFC1123Z
@ -62,5 +77,5 @@ func (ts TimeStamp) FormatShort() string {
// IsZero is zero time // IsZero is zero time
func (ts TimeStamp) IsZero() bool { func (ts TimeStamp) IsZero() bool {
return ts.AsTime().IsZero() return ts.AsTimeInLocation(time.Local).IsZero()
} }

@ -1959,10 +1959,6 @@ $(document).ready(function () {
// Show exact time // Show exact time
$('.time-since').each(function () { $('.time-since').each(function () {
const time = new Date($(this).attr('title'))
if (!isNaN(time)){
$(this).attr('title', time.toLocaleString())
}
$(this).addClass('poping up').attr('data-content', $(this).attr('title')).attr('data-variation', 'inverted tiny').attr('title', ''); $(this).addClass('poping up').attr('data-content', $(this).attr('title')).attr('data-variation', 'inverted tiny').attr('title', '');
}); });

@ -24,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
) )
const ( const (
@ -78,7 +79,7 @@ var sysStatus struct {
} }
func updateSystemStatus() { func updateSystemStatus() {
sysStatus.Uptime = base.TimeSincePro(startTime, "en") sysStatus.Uptime = timeutil.TimeSincePro(startTime, "en")
m := new(runtime.MemStats) m := new(runtime.MemStats)
runtime.ReadMemStats(m) runtime.ReadMemStats(m)

@ -16,6 +16,7 @@ import (
issue_indexer "code.gitea.io/gitea/modules/indexer/issues" issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
"code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
@ -183,9 +184,9 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
// "201": // "201":
// "$ref": "#/responses/Issue" // "$ref": "#/responses/Issue"
var deadlineUnix util.TimeStamp var deadlineUnix timeutil.TimeStamp
if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) {
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
} }
issue := &models.Issue{ issue := &models.Issue{
@ -310,9 +311,9 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
} }
// Update the deadline // Update the deadline
var deadlineUnix util.TimeStamp var deadlineUnix timeutil.TimeStamp
if form.Deadline != nil && !form.Deadline.IsZero() && ctx.Repo.CanWrite(models.UnitTypeIssues) { if form.Deadline != nil && !form.Deadline.IsZero() && ctx.Repo.CanWrite(models.UnitTypeIssues) {
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
} }
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
@ -430,12 +431,12 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) {
return return
} }
var deadlineUnix util.TimeStamp var deadlineUnix timeutil.TimeStamp
var deadline time.Time var deadline time.Time
if form.Deadline != nil && !form.Deadline.IsZero() { if form.Deadline != nil && !form.Deadline.IsZero() {
deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(),
23, 59, 59, 0, form.Deadline.Location()) 23, 59, 59, 0, form.Deadline.Location())
deadlineUnix = util.TimeStamp(deadline.Unix()) deadlineUnix = timeutil.TimeStamp(deadline.Unix())
} }
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {

@ -9,9 +9,8 @@ import (
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
) )
// ListMilestones list milestones for a repository // ListMilestones list milestones for a repository
@ -127,7 +126,7 @@ func CreateMilestone(ctx *context.APIContext, form api.CreateMilestoneOption) {
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
Name: form.Title, Name: form.Title,
Content: form.Description, Content: form.Description,
DeadlineUnix: util.TimeStamp(form.Deadline.Unix()), DeadlineUnix: timeutil.TimeStamp(form.Deadline.Unix()),
} }
if err := models.NewMilestone(milestone); err != nil { if err := models.NewMilestone(milestone); err != nil {
@ -187,7 +186,7 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
milestone.Content = *form.Description milestone.Content = *form.Description
} }
if form.Deadline != nil && !form.Deadline.IsZero() { if form.Deadline != nil && !form.Deadline.IsZero() {
milestone.DeadlineUnix = util.TimeStamp(form.Deadline.Unix()) milestone.DeadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
} }
if err := models.UpdateMilestone(milestone); err != nil { if err := models.UpdateMilestone(milestone); err != nil {

@ -17,7 +17,7 @@ import (
"code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/pull" "code.gitea.io/gitea/modules/pull"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// ListPullRequests returns a list of all PRs // ListPullRequests returns a list of all PRs
@ -247,9 +247,9 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption
return return
} }
var deadlineUnix util.TimeStamp var deadlineUnix timeutil.TimeStamp
if form.Deadline != nil { if form.Deadline != nil {
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
} }
maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) maxIndex, err := models.GetMaxIndexOfIssue(repo.ID)
@ -375,9 +375,9 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
} }
// Update Deadline // Update Deadline
var deadlineUnix util.TimeStamp var deadlineUnix timeutil.TimeStamp
if form.Deadline != nil && !form.Deadline.IsZero() { if form.Deadline != nil && !form.Deadline.IsZero() {
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
} }
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {

@ -9,6 +9,7 @@ import (
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
) )
// TemplatePreview render for previewing the indicated template // TemplatePreview render for previewing the indicated template
@ -18,8 +19,8 @@ func TemplatePreview(ctx *context.Context) {
ctx.Data["AppVer"] = setting.AppVer ctx.Data["AppVer"] = setting.AppVer
ctx.Data["AppUrl"] = setting.AppURL ctx.Data["AppUrl"] = setting.AppURL
ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374"
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language())
ctx.Data["CurDbValue"] = "" ctx.Data["CurDbValue"] = ""
ctx.HTML(200, base.TplName(ctx.Params("*"))) ctx.HTML(200, base.TplName(ctx.Params("*")))

@ -7,7 +7,7 @@ package private
import ( import (
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
macaron "gopkg.in/macaron.v1" macaron "gopkg.in/macaron.v1"
) )
@ -34,7 +34,7 @@ func UpdatePublicKeyInRepo(ctx *macaron.Context) {
}) })
return return
} }
deployKey.UpdatedUnix = util.TimeStampNow() deployKey.UpdatedUnix = timeutil.TimeStampNow()
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil { if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
ctx.JSON(500, map[string]interface{}{ ctx.JSON(500, map[string]interface{}{
"err": err.Error(), "err": err.Error(),

@ -14,7 +14,6 @@ import (
"strings" "strings"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
@ -22,7 +21,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
const ( const (
@ -212,7 +211,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
if index == 0 { if index == 0 {
// User avatar image // User avatar image
avatar := "" avatar := ""
commitSince := base.TimeSinceUnix(util.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string)) commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string))
if commit.User != nil { if commit.User != nil {
authorName := commit.Author.Name authorName := commit.Author.Name
if len(commit.User.FullName) > 0 { if len(commit.User.FullName) > 0 {

@ -25,7 +25,7 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
) )
// HTTP implmentation git smart HTTP protocol // HTTP implmentation git smart HTTP protocol
@ -203,7 +203,7 @@ func HTTP(ctx *context.Context) {
return return
} }
} }
token.UpdatedUnix = util.TimeStampNow() token.UpdatedUnix = timeutil.TimeStampNow()
if err = models.UpdateAccessToken(token); err != nil { if err = models.UpdateAccessToken(token); err != nil {
ctx.ServerError("UpdateAccessToken", err) ctx.ServerError("UpdateAccessToken", err)
} }

@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
) )
@ -120,7 +121,7 @@ func NewMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
Name: form.Title, Name: form.Title,
Content: form.Content, Content: form.Content,
DeadlineUnix: util.TimeStamp(deadline.Unix()), DeadlineUnix: timeutil.TimeStamp(deadline.Unix()),
}); err != nil { }); err != nil {
ctx.ServerError("NewMilestone", err) ctx.ServerError("NewMilestone", err)
return return
@ -190,7 +191,7 @@ func EditMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
} }
m.Name = form.Title m.Name = form.Title
m.Content = form.Content m.Content = form.Content
m.DeadlineUnix = util.TimeStamp(deadline.Unix()) m.DeadlineUnix = timeutil.TimeStamp(deadline.Unix())
if err = models.UpdateMilestone(m); err != nil { if err = models.UpdateMilestone(m); err != nil {
ctx.ServerError("UpdateMilestone", err) ctx.ServerError("UpdateMilestone", err)
return return
@ -223,7 +224,7 @@ func ChangeMilestonStatus(ctx *context.Context) {
ctx.Redirect(ctx.Repo.RepoLink + "/milestones?state=open") ctx.Redirect(ctx.Repo.RepoLink + "/milestones?state=open")
case "close": case "close":
if !m.IsClosed { if !m.IsClosed {
m.ClosedDateUnix = util.TimeStampNow() m.ClosedDateUnix = timeutil.TimeStampNow()
if err = models.ChangeMilestoneStatus(m, true); err != nil { if err = models.ChangeMilestoneStatus(m, true); err != nil {
ctx.ServerError("ChangeMilestoneStatus", err) ctx.ServerError("ChangeMilestoneStatus", err)
return return

@ -14,9 +14,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/Unknwon/com"
"mvdan.cc/xurls/v2"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@ -24,9 +21,12 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/routers/utils" "code.gitea.io/gitea/routers/utils"
"github.com/Unknwon/com"
"mvdan.cc/xurls/v2"
) )
const ( const (
@ -144,7 +144,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.Repo.Mirror.EnablePrune = form.EnablePrune ctx.Repo.Mirror.EnablePrune = form.EnablePrune
ctx.Repo.Mirror.Interval = interval ctx.Repo.Mirror.Interval = interval
if interval != 0 { if interval != 0 {
ctx.Repo.Mirror.NextUpdateUnix = util.TimeStampNow().AddDuration(interval) ctx.Repo.Mirror.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(interval)
} else { } else {
ctx.Repo.Mirror.NextUpdateUnix = 0 ctx.Repo.Mirror.NextUpdateUnix = 0
} }

@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
) )
@ -58,7 +59,7 @@ func MustEnableWiki(ctx *context.Context) {
type PageMeta struct { type PageMeta struct {
Name string Name string
SubURL string SubURL string
UpdatedUnix util.TimeStamp UpdatedUnix timeutil.TimeStamp
} }
// findEntryForFile finds the tree entry for a target filepath. // findEntryForFile finds the tree entry for a target filepath.
@ -413,7 +414,7 @@ func WikiPages(ctx *context.Context) {
pages = append(pages, PageMeta{ pages = append(pages, PageMeta{
Name: wikiName, Name: wikiName,
SubURL: models.WikiNameToSubURL(wikiName), SubURL: models.WikiNameToSubURL(wikiName),
UpdatedUnix: util.TimeStamp(c.Author.When.Unix()), UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
}) })
} }
ctx.Data["Pages"] = pages ctx.Data["Pages"] = pages

@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/recaptcha" "code.gitea.io/gitea/modules/recaptcha"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/go-macaron/captcha" "github.com/go-macaron/captcha"
@ -950,7 +951,7 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
models.SendActivateAccountMail(ctx.Context, u) models.SendActivateAccountMail(ctx.Context, u)
ctx.Data["IsSendRegisterMail"] = true ctx.Data["IsSendRegisterMail"] = true
ctx.Data["Email"] = u.Email ctx.Data["Email"] = u.Email
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
ctx.HTML(200, TplActivate) ctx.HTML(200, TplActivate)
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
@ -1096,7 +1097,7 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
models.SendActivateAccountMail(ctx.Context, u) models.SendActivateAccountMail(ctx.Context, u)
ctx.Data["IsSendRegisterMail"] = true ctx.Data["IsSendRegisterMail"] = true
ctx.Data["Email"] = u.Email ctx.Data["Email"] = u.Email
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
ctx.HTML(200, TplActivate) ctx.HTML(200, TplActivate)
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
@ -1123,7 +1124,7 @@ func Activate(ctx *context.Context) {
if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
ctx.Data["ResendLimited"] = true ctx.Data["ResendLimited"] = true
} else { } else {
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
models.SendActivateAccountMail(ctx.Context, ctx.User) models.SendActivateAccountMail(ctx.Context, ctx.User)
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
@ -1224,7 +1225,7 @@ func ForgotPasswdPost(ctx *context.Context) {
u, err := models.GetUserByEmail(email) u, err := models.GetUserByEmail(email)
if err != nil { if err != nil {
if models.IsErrUserNotExist(err) { if models.IsErrUserNotExist(err) {
ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language())
ctx.Data["IsResetSent"] = true ctx.Data["IsResetSent"] = true
ctx.HTML(200, tplForgotPassword) ctx.HTML(200, tplForgotPassword)
return return
@ -1251,7 +1252,7 @@ func ForgotPasswdPost(ctx *context.Context) {
log.Error("Set cache(MailResendLimit) fail: %v", err) log.Error("Set cache(MailResendLimit) fail: %v", err)
} }
ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language())
ctx.Data["IsResetSent"] = true ctx.Data["IsResetSent"] = true
ctx.HTML(200, tplForgotPassword) ctx.HTML(200, tplForgotPassword)
} }

@ -17,6 +17,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/recaptcha" "code.gitea.io/gitea/modules/recaptcha"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"github.com/go-macaron/captcha" "github.com/go-macaron/captcha"
) )
@ -446,7 +447,7 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si
models.SendActivateAccountMail(ctx.Context, u) models.SendActivateAccountMail(ctx.Context, u)
ctx.Data["IsSendRegisterMail"] = true ctx.Data["IsSendRegisterMail"] = true
ctx.Data["Email"] = u.Email ctx.Data["Email"] = u.Email
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
ctx.HTML(200, TplActivate) ctx.HTML(200, TplActivate)
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {

@ -7,7 +7,6 @@ package user
import ( import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/go-macaron/binding"
"net/url" "net/url"
"strings" "strings"
@ -17,9 +16,10 @@ import (
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/timeutil"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/go-macaron/binding"
) )
const ( const (
@ -118,7 +118,7 @@ func newAccessTokenResponse(grant *models.OAuth2Grant) (*AccessTokenResponse, *A
} }
} }
// generate access token to access the API // generate access token to access the API
expirationDate := util.TimeStampNow().Add(setting.OAuth2.AccessTokenExpirationTime) expirationDate := timeutil.TimeStampNow().Add(setting.OAuth2.AccessTokenExpirationTime)
accessToken := &models.OAuth2Token{ accessToken := &models.OAuth2Token{
GrantID: grant.ID, GrantID: grant.ID,
Type: models.TypeAccessToken, Type: models.TypeAccessToken,
@ -135,7 +135,7 @@ func newAccessTokenResponse(grant *models.OAuth2Grant) (*AccessTokenResponse, *A
} }
// generate refresh token to request an access token after it expired later // generate refresh token to request an access token after it expired later
refreshExpirationDate := util.TimeStampNow().Add(setting.OAuth2.RefreshTokenExpirationTime * 60 * 60).AsTime().Unix() refreshExpirationDate := timeutil.TimeStampNow().Add(setting.OAuth2.RefreshTokenExpirationTime * 60 * 60).AsTime().Unix()
refreshToken := &models.OAuth2Token{ refreshToken := &models.OAuth2Token{
GrantID: grant.ID, GrantID: grant.ID,
Counter: grant.Counter, Counter: grant.Counter,

@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
) )
const ( const (
@ -112,7 +113,7 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) {
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err) log.Error("Set cache(MailResendLimit) fail: %v", err)
} }
ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()))) ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())))
} else { } else {
ctx.Flash.Success(ctx.Tr("settings.add_email_success")) ctx.Flash.Success(ctx.Tr("settings.add_email_success"))
} }

@ -9770,7 +9770,7 @@
"description": "TimeStamp defines a timestamp", "description": "TimeStamp defines a timestamp",
"type": "integer", "type": "integer",
"format": "int64", "format": "int64",
"x-go-package": "code.gitea.io/gitea/modules/util" "x-go-package": "code.gitea.io/gitea/modules/timeutil"
}, },
"TrackedTime": { "TrackedTime": {
"description": "TrackedTime worked time for an issue / pr", "description": "TrackedTime worked time for an issue / pr",

Loading…
Cancel
Save