diff --git a/docs/exercises.md b/docs/exercises.md
index 7a88f72..db87686 100644
--- a/docs/exercises.md
+++ b/docs/exercises.md
@@ -68,6 +68,7 @@ title: Exercises
107_image_processing_utility - Image processing (Hard)
108_basic_key_value_store - Key-value store (Hard)
109_epoch - Time conversion (Beginner)
+ 120_time - Time functions exercise (Beginner)
diff --git a/internal/exercises/catalog.yaml b/internal/exercises/catalog.yaml
index f60c3bd..7488e0e 100644
--- a/internal/exercises/catalog.yaml
+++ b/internal/exercises/catalog.yaml
@@ -212,6 +212,14 @@ projects:
- "Use sort.Sort() to sort slices with your custom comparison logic"
- "Remember to make copies of slices to avoid modifying the original"
+- slug: 120_time
+ title: "Time"
+ description: "Practice working with Go’s time package: formatting dates and computing day differences."
+ template: "templates/time.go"
+ test: "templates/time_test.go"
+ hints:
+ - "Use time.Format with layout \"2006-01-02\""
+ - "Subtract two times to get a Duration, then convert to hours and divide by 24"
- slug: 38_time_formatting
title: "Time Formatting"
difficulty: beginner
diff --git a/internal/exercises/solutions/120_time/time.go b/internal/exercises/solutions/120_time/time.go
new file mode 100644
index 0000000..d3afb06
--- /dev/null
+++ b/internal/exercises/solutions/120_time/time.go
@@ -0,0 +1,50 @@
+package time
+
+import "time"
+
+// FormatDate formats a time.Time into "YYYY-MM-DD".
+func FormatDate(t time.Time) string {
+ return t.Format("2006-01-02")
+}
+
+// FormatDateTime formats a time.Time into "YYYY-MM-DD HH:MM:SS".
+func FormatDateTime(t time.Time) string {
+ return t.Format("2006-01-02 15:04:05")
+}
+
+// DaysBetween returns the number of days between two dates.
+// Positive if end > start, negative if end < start.
+//
+// Note: This implementation divides the duration by 24 hours.
+// When dates span a daylight saving time (DST) transition, the result
+// may be off by ±1 hour. For exact day counts across DST, consider
+// normalizing both dates to UTC or comparing date components at midnight.
+func DaysBetween(start, end time.Time) int {
+ return int(end.Sub(start).Hours() / 24)
+}
+
+
+// AddDays adds a specified number of days to a date and returns the new date.
+func AddDays(t time.Time, days int) time.Time {
+ return t.AddDate(0, 0, days)
+}
+
+// ParseDate parses a string in "YYYY-MM-DD" format into a time.Time.
+// Returns zero time if parsing fails.
+func ParseDate(s string) time.Time {
+ t, err := time.Parse("2006-01-02", s)
+ if err != nil {
+ return time.Time{}
+ }
+ return t
+}
+
+// ParseDateTime parses a string in "YYYY-MM-DD HH:MM:SS" format into a time.Time.
+// Returns zero time if parsing fails.
+func ParseDateTime(s string) time.Time {
+ t, err := time.Parse("2006-01-02 15:04:05", s)
+ if err != nil {
+ return time.Time{}
+ }
+ return t
+}
diff --git a/internal/exercises/templates/120_time/time.go b/internal/exercises/templates/120_time/time.go
new file mode 100644
index 0000000..2c80291
--- /dev/null
+++ b/internal/exercises/templates/120_time/time.go
@@ -0,0 +1,44 @@
+package timeutils
+
+import "time"
+
+// FormatDate formats a time.Time into "YYYY-MM-DD".
+func FormatDate(t time.Time) string {
+ return t.Format("2006-01-02")
+}
+
+// FormatDateTime formats a time.Time into "YYYY-MM-DD HH:MM:SS".
+func FormatDateTime(t time.Time) string {
+ return t.Format("2006-01-02 15:04:05")
+}
+
+// DaysBetween returns the number of days between two dates.
+// Positive if end > start, negative if end < start.
+func DaysBetween(start, end time.Time) int {
+ return int(end.Sub(start).Hours() / 24)
+}
+
+// AddDays adds a specified number of days to a date and returns the new date.
+func AddDays(t time.Time, days int) time.Time {
+ return t.AddDate(0, 0, days)
+}
+
+// ParseDate parses a string in "YYYY-MM-DD" format into a time.Time.
+// Returns zero time if parsing fails.
+func ParseDate(s string) time.Time {
+ t, err := time.Parse("2006-01-02", s)
+ if err != nil {
+ return time.Time{}
+ }
+ return t
+}
+
+// ParseDateTime parses a string in "YYYY-MM-DD HH:MM:SS" format into a time.Time.
+// Returns zero time if parsing fails.
+func ParseDateTime(s string) time.Time {
+ t, err := time.Parse("2006-01-02 15:04:05", s)
+ if err != nil {
+ return time.Time{}
+ }
+ return t
+}
diff --git a/internal/exercises/templates/120_time/time_test.go b/internal/exercises/templates/120_time/time_test.go
new file mode 100644
index 0000000..0624d76
--- /dev/null
+++ b/internal/exercises/templates/120_time/time_test.go
@@ -0,0 +1,82 @@
+package timeutils_test
+
+import (
+ "testing"
+ "time"
+
+ timeutils "github.com/zhravan/golearn/internal/exercises/templates/120_time"
+)
+
+// Helper to quickly create a date
+func mustDate(year int, month time.Month, day int) time.Time {
+ return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
+}
+
+// --- Tests for FormatDate ---
+func TestFormatDate(t *testing.T) {
+ d := mustDate(2025, time.October, 2)
+ want := "2025-10-02"
+ got := timeutils.FormatDate(d)
+ if got != want {
+ t.Fatalf("FormatDate(%v) = %q; want %q", d, got, want)
+ }
+}
+
+// --- Tests for FormatDateTime ---
+func TestFormatDateTime(t *testing.T) {
+ d := mustDate(2025, time.October, 2)
+ want := "2025-10-02 00:00:00"
+ got := timeutils.FormatDateTime(d)
+ if got != want {
+ t.Fatalf("FormatDateTime(%v) = %q; want %q", d, got, want)
+ }
+}
+
+// --- Tests for DaysBetween ---
+func TestDaysBetween(t *testing.T) {
+ start := mustDate(2025, time.October, 1)
+ end := mustDate(2025, time.October, 11)
+
+ got := timeutils.DaysBetween(start, end)
+ want := 10
+ if got != want {
+ t.Fatalf("DaysBetween(%v, %v) = %d; want %d", start, end, got, want)
+ }
+
+ // negative difference
+ got = timeutils.DaysBetween(end, start)
+ want = -10
+ if got != want {
+ t.Fatalf("DaysBetween(%v, %v) = %d; want %d", end, start, got, want)
+ }
+}
+
+// --- Tests for AddDays ---
+func TestAddDays(t *testing.T) {
+ d := mustDate(2025, time.October, 1)
+ got := timeutils.AddDays(d, 10)
+ want := mustDate(2025, time.October, 11)
+ if !got.Equal(want) {
+ t.Fatalf("AddDays(%v, 10) = %v; want %v", d, got, want)
+ }
+}
+
+// --- Tests for ParseDate ---
+func TestParseDate(t *testing.T) {
+ input := "2025-10-02"
+ want := mustDate(2025, time.October, 2)
+ got := timeutils.ParseDate(input)
+ if !got.Equal(want) {
+ t.Fatalf("ParseDate(%q) = %v; want %v", input, got, want)
+ }
+}
+
+// --- Tests for ParseDateTime ---
+func TestParseDateTime(t *testing.T) {
+ input := "2025-10-02 00:00:00"
+ want := mustDate(2025, time.October, 2)
+ got := timeutils.ParseDateTime(input)
+ if !got.Equal(want) {
+ t.Fatalf("ParseDateTime(%q) = %v; want %v", input, got, want)
+ }
+}