Question
I want to format the current time in Go using the pattern yyyyMMddHHmmss.
t := time.Now()
fmt.Println(t.Format("yyyyMMddHHmmss"))
However, the output is:
yyyyMMddHHmmss
Why does this happen, and how can I correctly format the current time in that style?
Short Answer
By the end of this page, you will understand how Go time formatting works, why yyyyMMddHHmmss does not behave like date patterns in some other languages, and how to correctly format the current time as a compact timestamp such as 20260610153045.
Concept
In Go, time formatting does not use pattern letters like yyyy, MM, dd, HH, mm, and ss.
Instead, Go uses a reference time:
Mon Jan 2 15:04:05 MST 2006
To format a date or time, you rewrite that reference time in the layout you want.
For example:
t := time.Now()
fmt.Println(t.Format("20060102150405"))
This produces output in the style:
20260610153045
Why your code prints the layout literally
In Go, this line:
t.Format("yyyyMMddHHmmss")
does not contain any recognized reference-time values. Since Go does not treat yyyy or MM as special tokens, it prints them as normal text.
Why this matters
Time formatting is used everywhere in programming:
- log filenames
- timestamps in APIs
- database exports
- backup file names
- sortable identifiers
If you come from Java, C#, Python, or JavaScript libraries, Go's formatting style may feel unusual at first. But once you learn the reference-time approach, it becomes very predictable.
Mental Model
Think of Go time formatting like using a stencil example instead of symbolic placeholders.
In many languages, you write instructions such as:
yyyy= yearMM= monthdd= day
In Go, you do not write instructions. You write a sample date showing the exact arrangement you want.
If you want:
- year, month, day, hour, minute, second
you take the Go reference date and place its parts in that order:
2006 01 02 15 04 05
Remove separators if needed:
20060102150405
So the layout is not a formula like yyyyMMddHHmmss. It is a model timestamp that Go uses as a template.
Syntax and Examples
The basic syntax is:
t := time.Now()
formatted := t.Format("20060102150405")
fmt.Println(formatted)
Example: compact timestamp
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t.Format("20060102150405"))
}
Example output:
20260610153045
Example: readable date and time
fmt.Println(t.Format("2006-01-02 15:04:05"))
Possible output:
2026-06-10 15:30:45
Example: date only
fmt.Println(t.Format("2006-01-02"))
Possible output:
2026-06-10
Important reference values in Go
2006= year01= zero-padded month02= zero-padded day15= hour in 24-hour format04= minute05= second
These exact numbers matter.
Step by Step Execution
Consider this code:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, 6, 10, 15, 30, 45, 0, time.UTC)
result := t.Format("20060102150405")
fmt.Println(result)
}
Step-by-step
-
time.Date(...)creates a specific time value:- year =
2026 - month =
6 - day =
10 - hour =
15 - minute =
30 - second =
45
- year =
-
t.Format("20060102150405")tells Go to output the time in this order:2006→ year01→ month02→ day15→ hour04→ minute05→ second
-
Go substitutes each part from
tinto that layout. -
The final output becomes:
20260610153045
What happens with the wrong layout
t.Format("yyyyMMddHHmmss")
Go reads that as plain text because yyyy, MM, dd, HH, mm, and ss are not Go layout values.
So the output is simply:
yyyyMMddHHmmss
Real World Use Cases
Compact timestamps like yyyyMMddHHmmss style values are common in real programs.
File naming
filename := "backup_" + time.Now().Format("20060102150405") + ".zip"
Example result:
backup_20260610153045.zip
This is useful because the filenames sort naturally by date.
Logging
You may include precise timestamps in logs or generated report names.
logID := time.Now().Format("20060102150405")
fmt.Println("log batch:", logID)
Export jobs
Data export scripts often generate names like:
orders_20260610153045.csv
API payloads
Some systems expect compact date strings rather than ISO timestamps.
timestamp := time.Now().Format("20060102150405")
Batch processing
Scheduled jobs may store run IDs using the current time:
runID := "job-" + time.Now().Format("20060102150405")
Real Codebase Usage
In real Go projects, developers usually combine time formatting with a few common patterns.
Creating stable file names
func buildBackupName() string {
return "backup_" + time.Now().Format("20060102150405") + ".sql"
}
Using UTC for consistency
When timestamps are shared across servers or services, UTC is often safer.
stamp := time.Now().UTC().Format("20060102150405")
This avoids timezone confusion.
Guarding formatting behind helper functions
Instead of repeating layouts everywhere, teams often centralize them.
func CompactTimestamp(t time.Time) string {
return t.Format("20060102150405")
}
This makes code easier to read and change later.
Validation and parsing pairs
If one part of the system formats a timestamp, another part may parse it.
layout := "20060102150405"
value := time.Now().Format(layout)
parsed, err := time.Parse(layout, value)
if err != nil {
fmt.Println("parse error:", err)
}
_ = parsed
Configuration constants
In larger codebases, layouts are often stored as constants.
const compactTimeLayout = "20060102150405"
That avoids typos and duplication.
Common Mistakes
1. Using yyyyMMddHHmmss like other languages
Broken code:
t := time.Now()
fmt.Println(t.Format("yyyyMMddHHmmss"))
Problem:
- Go does not use
yyyy,MM,dd,HH,mm,sstokens.
Fix:
fmt.Println(t.Format("20060102150405"))
2. Using the wrong reference values
Broken code:
fmt.Println(t.Format("YYYYMMDDhhmmss"))
Problem:
- Capitalization and token names do not matter in the way they do in some other languages.
- Go needs the exact reference date numbers.
Fix:
fmt.Println(t.Format("20060102150405"))
3. Mixing 12-hour and 24-hour formats
In Go:
15= 24-hour clock03= 12-hour clock
Broken code:
fmt.Println(t.Format("20060102030405"))
This may give the wrong hour format for your use case.
Fix:
fmt.Println(t.Format("20060102150405"))
4. Forgetting timezone consistency
fmt.Println(time.Now().Format("20060102150405"))
This uses local time. In distributed systems, local time may differ between servers.
Safer option when needed:
fmt.Println(time.Now().UTC().Format("20060102150405"))
5. Repeating magic strings everywhere
Broken pattern:
name1 := time.Now().Format("20060102150405")
name2 := time.Now().Format("20060102150405")
name3 := time.Now().Format("20060102150405")
Better:
const compactLayout = "20060102150405"
fmt.Println(time.Now().Format(compactLayout))
This improves maintainability.
Comparisons
| Concept | Go approach | Common in other languages | Example |
|---|---|---|---|
| Year | 2006 | yyyy | 2026 |
| Month | 01 | MM | 06 |
| Day | 02 | dd | 10 |
| Hour (24h) | 15 | HH | 15 |
| Minute | 04 | mm | 30 |
| Second | 05 | ss | 45 |
Go layout vs pattern-based formatting
| Style | Example | Used by |
|---|---|---|
| Reference time | 20060102150405 | Go |
| Pattern tokens | yyyyMMddHHmmss | Java, C#, many libraries |
Format vs Parse
| Method | Purpose | Example |
|---|---|---|
Format | Convert time.Time to string | t.Format("20060102150405") |
Parse | Convert string to time.Time | time.Parse("20060102150405", s) |
Local time vs UTC
| Choice | When to use | Example |
|---|---|---|
| Local time | User-facing timestamps | time.Now().Format(...) |
| UTC | Logs, APIs, servers, shared systems | time.Now().UTC().Format(...) |
Cheat Sheet
// Compact timestamp
layout := "20060102150405"
formatted := time.Now().Format(layout)
// With separators
formatted = time.Now().Format("2006-01-02 15:04:05")
// Date only
formatted = time.Now().Format("2006-01-02")
// UTC
formatted = time.Now().UTC().Format("20060102150405")
// Parse back
parsed, err := time.Parse("20060102150405", "20260610153045")
Core rule
Go uses this reference time:
Mon Jan 2 15:04:05 MST 2006
Most useful layout pieces
2006= year01= month02= day15= hour (24-hour)04= minute05= second
For yyyyMMddHHmmss style in Go
Use:
"20060102150405"
Common edge cases
yyyyMMddHHmmssdoes not work in Go15is 24-hour format- use
.UTC()if timezone consistency matters - store layouts in constants for reuse
FAQ
Why does yyyyMMddHHmmss print literally in Go?
Because Go does not use symbolic date pattern letters. It only recognizes layouts based on the reference time Mon Jan 2 15:04:05 MST 2006.
What is the Go equivalent of yyyyMMddHHmmss?
Use:
"20060102150405"
Why does Go use 2006-01-02 15:04:05 instead of tokens like yyyy?
That is how the Go standard library was designed. You format time by rearranging the reference date rather than using symbolic placeholders.
How do I format the current time in UTC in Go?
Use:
time.Now().UTC().Format("20060102150405")
Can I parse a string like 20260610153045 back into a time.Time?
Yes.
layout := "20060102150405"
t, err := time.Parse(layout, "20260610153045")
What does 15 mean in a Go time layout?
It represents the hour in 24-hour format.
Is 01 the month and 02 the day in Go layouts?
Yes. Those are fixed parts of the Go reference time.
Should I save the layout string in a constant?
Yes, especially if you use it in multiple places. It reduces duplication and mistakes.
Mini Project
Description
Build a small Go program that creates a timestamped backup filename. This demonstrates how to format the current time in Go using the compact yyyyMMddHHmmss style layout and use that value in a practical way.
Goal
Generate a filename like backup_20260610153045.sql using the current time.
Requirements
Requirement 1 Requirement 2 Requirement 3
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.