Here's a cautionary tale of why AI isn't always the answer in software development...
I was banging away on my current project recently, and I had need of a Go module that could format dates according to a "locale" setting that is part of a user's preferences. I asked Google Gemini about it, because Google made Go, and Google made Gemini, so it should know if anything would, right? It gave me this answer:
No, you can't directly get a Go
time.Formatlayout string (like"01/02/2006") from a BCP 47 tag using thegolang.org/x/textpackage.Instead, the package provides a more powerful, locale-aware
Formatterobject. You create this formatter for a specific language and then use it to formattime.Timeobjects directly. This approach is more robust because it handles the complex rules and different date lengths (short, long, etc.) defined in the Unicode CLDR (Common Locale Data Repository).
And it provided a decent-looking code sample:
package main
import (
"fmt"
"log"
"time"
"golang.org/x/text/date"
"golang.org/x/text/language"
"golang.org/x/text/message"
)
func main() {
// The time we want to format.
now := time.Now()
// A list of BCP 47 language tags to demonstrate with.
tags := []string{"en-US", "fr-FR", "de-DE", "ja-JP"}
fmt.Printf("Formatting time: %s\n\n", now.Format(time.RFC1123))
for _, tagStr := range tags {
// 1. Parse the BCP 47 string into a language.Tag object.
langTag, err := language.Parse(tagStr)
if err != nil {
log.Fatalf("Failed to parse language tag %s: %v", tagStr, err)
}
// 2. Create a message.Printer for the specific locale.
// This printer is the key component that knows the rules for the given language.
p := message.NewPrinter(langTag)
// 3. Create date formatters for different styles.
// The formatter uses the printer's locale to determine the correct format.
formatterShort := date.New(p, date.Short) // e.g., 10/12/25
formatterLong := date.New(p, date.Long) // e.g., October 12, 2025
formatterFull := date.New(p, date.Full) // e.g., Sunday, October 12, 2025
fmt.Printf("--- Locale: %s ---\n", tagStr)
fmt.Printf(" Short: %s\n", formatterShort.Format(now))
fmt.Printf(" Long: %s\n", formatterLong.Format(now))
fmt.Printf(" Full: %s\n", formatterFull.Format(now))
fmt.Println()
}
}
Looks good, right? Except if you look at the actual documentation for the package, it shows nothing in it but a bunch of constants! There's no date.New method.
I complained to Gemini:
date.Newis not a valid function in Go Text version 0.30.0. Is there something else I can use?
And it suggested:
You are absolutely right. The
date.Newfunction was part of an older API in thex/textpackage that has since been removed.The modern way to achieve locale-aware date formatting is to use a
message.Printerwith ICU MessageFormat strings. This is a more powerful and standardized approach. Instead of creating a separate formatter object, you simply pass thetime.Timevalue to the printer'sSprintffunction with a special format string.Here is the updated, correct way to format dates for different locales.
And the code sample:
package main
import (
"fmt"
"log"
"time"
"golang.org/x/text/language"
"golang.org/x/text/message"
)
func main() {
// The time we want to format.
now := time.Now()
// A list of BCP 47 language tags to demonstrate with.
tags := []string{"en-US", "fr-FR", "de-DE", "ja-JP"}
fmt.Printf("Formatting time: %s\n\n", now.Format(time.RFC1123))
for _, tagStr := range tags {
// 1. Parse the BCP 47 string into a language.Tag object.
langTag, err := language.Parse(tagStr)
if err != nil {
log.Fatalf("Failed to parse language tag %s: %v", tagStr, err)
}
// 2. Create a message.Printer for the specific locale.
p := message.NewPrinter(langTag)
// 3. Use Sprintf with ICU MessageFormat strings to format the date.
// The syntax is {argumentIndex, type, style}.
shortDate := p.Sprintf("{0,date,short}", now)
mediumDate := p.Sprintf("{0,date,medium}", now) // Medium is often the default
longDate := p.Sprintf("{0,date,long}", now)
fullDate := p.Sprintf("{0,date,full}", now)
fmt.Printf("--- Locale: %s ---\n", tagStr)
fmt.Printf(" Short: %s\n", shortDate)
fmt.Printf(" Medium: %s\n", mediumDate)
fmt.Printf(" Long: %s\n", longDate)
fmt.Printf(" Full: %s\n", fullDate)
fmt.Println()
}
}
(I should note that I checked the version history of the date package, and didn't see the date.New function in there, going back quite a ways. But I digress...)
I tried that solution, using a format string like this:
pr.Sprintf("{0,date,medium} {0,time,medium}", dateVal)
And the result...didn't work. The display showed just "{0,date,medium} {0,time,medium}". No good here either!
In the end, I abandoned the AI's solutions, and googled around for a better one, finally hitting on Klaus Post's lctime module, a port of a strftime(3)-like library call to Go, using data based on glibc locale files. Yes, it's old, and hasn't been maintained since at least 2021 (when the GitHub repo was marked read-only), but, gosh darn it, it worked.
Therein lies a cautionary tale: always check what the AI is giving you against the real world. Even if it looks sure of itself, you may be going down the wrong path. (Makes me worry even more about the vibe-coders.) Also, maybe I should have gotten a "second opinion" from ChatGPT or Claude, once I saw Gemini's work wasn't gonna cut it.
Nice thing though is...I'm beginning to feel more like an engineer again. More on that later, perhaps.