diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go
index 698014afeb..1d7592926b 100644
--- a/models/issues/tracked_time.go
+++ b/models/issues/tracked_time.go
@@ -6,6 +6,7 @@ package issues
 import (
 	"context"
 	"errors"
+	"fmt"
 	"time"
 
 	"code.gitea.io/gitea/models/db"
@@ -173,10 +174,12 @@ func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Tim
 	}
 
 	if _, err := CreateComment(ctx, &CreateCommentOptions{
-		Issue:   issue,
-		Repo:    issue.Repo,
-		Doer:    user,
-		Content: util.SecToTime(amount),
+		Issue: issue,
+		Repo:  issue.Repo,
+		Doer:  user,
+		// Content before v1.21 did store the formated string instead of seconds,
+		// so use "|" as delimeter to mark the new format
+		Content: fmt.Sprintf("|%d", amount),
 		Type:    CommentTypeAddTimeManual,
 		TimeID:  t.ID,
 	}); err != nil {
@@ -251,10 +254,12 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
 		return err
 	}
 	if _, err := CreateComment(ctx, &CreateCommentOptions{
-		Issue:   issue,
-		Repo:    issue.Repo,
-		Doer:    user,
-		Content: "- " + util.SecToTime(removedTime),
+		Issue: issue,
+		Repo:  issue.Repo,
+		Doer:  user,
+		// Content before v1.21 did store the formated string instead of seconds,
+		// so use "|" as delimeter to mark the new format
+		Content: fmt.Sprintf("|%d", removedTime),
 		Type:    CommentTypeDeleteTimeManual,
 	}); err != nil {
 		return err
@@ -280,10 +285,12 @@ func DeleteTime(t *TrackedTime) error {
 	}
 
 	if _, err := CreateComment(ctx, &CreateCommentOptions{
-		Issue:   t.Issue,
-		Repo:    t.Issue.Repo,
-		Doer:    t.User,
-		Content: "- " + util.SecToTime(t.Time),
+		Issue: t.Issue,
+		Repo:  t.Issue.Repo,
+		Doer:  t.User,
+		// Content before v1.21 did store the formated string instead of seconds,
+		// so use "|" as delimeter to mark the new format
+		Content: fmt.Sprintf("|%d", t.Time),
 		Type:    CommentTypeDeleteTimeManual,
 	}); err != nil {
 		return err
diff --git a/models/issues/tracked_time_test.go b/models/issues/tracked_time_test.go
index baa170b201..37ba1cfdc4 100644
--- a/models/issues/tracked_time_test.go
+++ b/models/issues/tracked_time_test.go
@@ -35,7 +35,7 @@ func TestAddTime(t *testing.T) {
 	assert.Equal(t, int64(3661), tt.Time)
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeAddTimeManual, PosterID: 3, IssueID: 1})
-	assert.Equal(t, "1 hour 1 minute", comment.Content)
+	assert.Equal(t, "|3661", comment.Content)
 }
 
 func TestGetTrackedTimes(t *testing.T) {
diff --git a/modules/util/sec_to_time.go b/modules/util/sec_to_time.go
index 017ed45f8c..ad0fb1a68b 100644
--- a/modules/util/sec_to_time.go
+++ b/modules/util/sec_to_time.go
@@ -15,7 +15,9 @@ import (
 // 1563418		-> 2 weeks 4 days
 // 3937125s     -> 1 month 2 weeks
 // 45677465s	-> 1 year 6 months
-func SecToTime(duration int64) string {
+func SecToTime(durationVal any) string {
+	duration, _ := ToInt64(durationVal)
+
 	formattedTime := ""
 
 	// The following four variables are calculated by taking
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index a9ce1cc1e7..7d8ec3a6f3 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -1647,9 +1647,22 @@ func ViewIssue(ctx *context.Context) {
 				return
 			}
 		} else if comment.Type == issues_model.CommentTypeAddTimeManual ||
-			comment.Type == issues_model.CommentTypeStopTracking {
+			comment.Type == issues_model.CommentTypeStopTracking ||
+			comment.Type == issues_model.CommentTypeDeleteTimeManual {
 			// drop error since times could be pruned from DB..
 			_ = comment.LoadTime()
+			if comment.Content != "" {
+				// Content before v1.21 did store the formated string instead of seconds,
+				// so "|" is used as delimeter to mark the new format
+				if comment.Content[0] != '|' {
+					// handle old time comments that have formatted text stored
+					comment.RenderedContent = comment.Content
+					comment.Content = ""
+				} else {
+					// else it's just a duration in seconds to pass on to the frontend
+					comment.Content = comment.Content[1:]
+				}
+			}
 		}
 
 		if comment.Type == issues_model.CommentTypeClose || comment.Type == issues_model.CommentTypeMergePull {
diff --git a/services/convert/issue_comment.go b/services/convert/issue_comment.go
index 2810c6c9bc..db48faa69e 100644
--- a/services/convert/issue_comment.go
+++ b/services/convert/issue_comment.go
@@ -11,6 +11,7 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/log"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/modules/util"
 )
 
 // ToComment converts a issues_model.Comment to the api.Comment format
@@ -66,6 +67,17 @@ func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_
 		return nil
 	}
 
+	if c.Content != "" {
+		if (c.Type == issues_model.CommentTypeAddTimeManual ||
+			c.Type == issues_model.CommentTypeStopTracking ||
+			c.Type == issues_model.CommentTypeDeleteTimeManual) &&
+			c.Content[0] == '|' {
+			// TimeTracking Comments from v1.21 on store the seconds instead of an formated string
+			// so we check for the "|" delimeter and convert new to legacy format on demand
+			c.Content = util.SecToTime(c.Content[1:])
+		}
+	}
+
 	comment := &api.TimelineComment{
 		ID:       c.ID,
 		Type:     c.Type.String(),
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index 5f1f506b27..5dbd530fa5 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -263,7 +263,12 @@
 				{{template "repo/issue/view_content/comments_delete_time" dict "ctxData" $ "comment" .}}
 				<div class="detail">
 					{{svg "octicon-clock"}}
-					<span class="text grey muted-links">{{.Content}}</span>
+					{{if .RenderedContent}}
+						{{/* compatibility with time comments made before v1.21 */}}
+						<span class="text grey muted-links">{{.RenderedContent}}</span>
+					{{else}}
+						<span class="text grey muted-links">{{.Content|Sec2Time}}</span>
+					{{end}}
 				</div>
 			</div>
 		{{else if eq .Type 14}}
@@ -277,7 +282,12 @@
 				{{template "repo/issue/view_content/comments_delete_time" dict "ctxData" $ "comment" .}}
 				<div class="detail">
 					{{svg "octicon-clock"}}
-					<span class="text grey muted-links">{{.Content}}</span>
+					{{if .RenderedContent}}
+						{{/* compatibility with time comments made before v1.21 */}}
+						<span class="text grey muted-links">{{.RenderedContent}}</span>
+					{{else}}
+						<span class="text grey muted-links">{{.Content|Sec2Time}}</span>
+					{{end}}
 				</div>
 			</div>
 		{{else if eq .Type 15}}
@@ -676,7 +686,12 @@
 				</span>
 				<div class="detail">
 					{{svg "octicon-clock"}}
-					<span class="text grey muted-links">{{.Content}}</span>
+					{{if .RenderedContent}}
+						{{/* compatibility with time comments made before v1.21 */}}
+						<span class="text grey muted-links">{{.RenderedContent}}</span>
+					{{else}}
+						<span class="text grey muted-links">- {{.Content|Sec2Time}}</span>
+					{{end}}
 				</div>
 			</div>
 		{{else if eq .Type 27}}