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.Format layout string (like "01/02/2006") from a BCP 47 tag using the golang.org/x/text package.

Instead, the package provides a more powerful, locale-aware Formatter object. You create this formatter for a specific language and then use it to format time.Time objects 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.New is 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.New function was part of an older API in the x/text package that has since been removed.

The modern way to achieve locale-aware date formatting is to use a message.Printer with ICU MessageFormat strings. This is a more powerful and standardized approach. Instead of creating a separate formatter object, you simply pass the time.Time value to the printer's Sprintf function 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.

...or show your appreciation some other way