# MySQL Driver parseTime=false Behavior for DATE and DATETIME Columns

> Explore go-sql-driver/mysql parseTime=false behavior. Learn how DATE and DATETIME columns return as raw byte slices, preserving MySQL wire format for your application.

- Repository: [Go SQL Drivers/mysql](https://github.com/go-sql-driver/mysql)
- Tags: internals
- Published: 2026-03-02

---

**When `parseTime=false`, the go-sql-driver/mysql driver returns `DATE` and `DATETIME` columns as raw `[]byte` slices instead of `time.Time` objects, leaving the MySQL wire format bytes unchanged for application-level handling.**

The `parseTime` DSN parameter in the `go-sql-driver/mysql` repository controls how temporal columns are materialized in Go. When set to `false` (the default), the driver bypasses time parsing entirely for `DATE`, `DATETIME`, `TIMESTAMP`, and `NEWDATE` columns, returning the raw server response as byte slices that can be scanned into `[]byte`, `string`, or `sql.RawBytes`.

## How parseTime=false Affects Date Column Handling

The driver stores the `parseTime` flag in the DSN configuration structure (`Config.ParseTime` in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go)). During row fetching, the text-row reader in [`packets.go`](https://github.com/go-sql-driver/mysql/blob/main/packets.go) evaluates this flag on a per-column basis to determine whether to invoke time parsing or pass through raw bytes.

When the driver encounters a temporal column type (`TIMESTAMP`, `DATETIME`, `DATE`, or `NEWDATE`), it checks `mc.parseTime` at [`packets.go`](https://github.com/go-sql-driver/mysql/blob/main/packets.go) lines 69-78:

- **If `parseTime=true`**: The driver calls `parseDateTime` (implemented in [`utils.go`](https://github.com/go-sql-driver/mysql/blob/main/utils.go) lines 108-177) to convert the MySQL byte representation into a `time.Time` value. This routine also maps the MySQL "zero-date" (`0000-00-00 00:00:00`) to the Go zero value `time.Time{}`.

- **If `parseTime=false`**: The driver assigns the raw byte slice (`[]byte`) directly to the destination value, bypassing `parseDateTime` entirely. The bytes remain in the MySQL wire format (e.g., `"2023-01-15"` for `DATE` or `"2023-01-15 12:34:56"` for `DATETIME`).

## Source Code Implementation Details

### DSN Configuration (dsn.go)

The `ParseTime` boolean field in the `Config` struct captures the DSN parameter. This value propagates to the connection struct (`mysqlConn`) and is accessed during row scanning operations.

### Row Reading Logic (packets.go)

In the text protocol row reader, the driver iterates over result set columns. For temporal types, the critical branch at lines 69-78 determines the conversion path:

```go
// Simplified logic from packets.go
case fieldTypeTimestamp, fieldTypeDatetime, fieldTypeDate, fieldTypeNewdate:
    if mc.parseTime {
        dest[i], err = parseDateTime(string(buf), mc.cfg.Loc)
    } else {
        dest[i] = buf // raw []byte
    }

```

### Date Parsing Routine (utils.go)

The `parseDateTime` function (lines 108-177) handles string-to-time conversion, including location awareness and zero-date normalization. When `parseTime=false`, this function is never invoked for temporal columns, eliminating parsing overhead and zero-date special handling.

## Practical Behavior and Edge Cases

### Zero-Date Handling

With `parseTime=false`, the MySQL zero-date (`0000-00-00 00:00:00`) is returned as the literal byte string `"0000-00-00 00:00:00"` (or `"0000-00-00"` for `DATE`). The driver does not convert this to Go's `time.Time{}` zero value.

### Type Scanning Implications

When `parseTime=false`, destination variables must match the raw byte type:

- **Valid scans**: `[]byte`, `string`, `sql.RawBytes`
- **Invalid scans**: `time.Time` (results in a conversion error: "unsupported driver -> value type []byte")

Attempting to scan a `DATE` column into a `time.Time` variable while `parseTime=false` produces an error similar to:

```

sql: Scan error on column index 0, name "d": converting driver.Value type []byte ("2023-01-15") to a time.Time: unsupported driver -> value type []byte

```

### Performance Considerations

Disabling time parsing removes the overhead of `parseDateTime`, which involves string parsing, validation, and location handling. This can improve throughput for applications that do not require `time.Time` objects or that perform their own date parsing.

## Code Example: parseTime=false in Practice

The following example demonstrates the behavior when querying `DATE` and `DATETIME` columns with `parseTime=false`:

```go
package main

import (
	"database/sql"
	"fmt"
	"log"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// DSN with parseTime disabled
	dsn := "user:password@tcp(127.0.0.1:3306)/testdb?parseTime=false"
	db, err := sql.Open("mysql", dsn)
	if err != nil { log.Fatal(err) }
	defer db.Close()

	// Assume a table: CREATE TABLE dates (d DATE, dt DATETIME);
	row := db.QueryRow("SELECT d, dt FROM dates LIMIT 1")

	// Scan into raw []byte – works
	var rawDate, rawDateTime []byte
	if err := row.Scan(&rawDate, &rawDateTime); err != nil {
		log.Fatalf("scan raw bytes: %v", err)
	}
	fmt.Printf("raw DATE:    %s\n", rawDate)    // e.g. "2023-01-15"
	fmt.Printf("raw DATETIME: %s\n", rawDateTime) // e.g. "2023-01-15 12:34:56"

	// Scan directly into time.Time – fails because driver returned []byte
	row = db.QueryRow("SELECT d FROM dates LIMIT 1")
	var t time.Time
	if err := row.Scan(&t); err != nil {
		// Example error:
		//   sql: Scan error on column index 0, name "d": converting driver.Value type []byte ("2023-01-15") to a time.Time: unsupported driver -> value type []byte
		fmt.Printf("expected error scanning into time.Time: %v\n", err)
	}
}

```

Changing the DSN to `parseTime=true` causes the driver to invoke `parseDateTime` from [`utils.go`](https://github.com/go-sql-driver/mysql/blob/main/utils.go), returning `time.Time` values and mapping zero-dates to `time.Time{}`.

## Summary

- **Raw bytes returned**: With `parseTime=false`, the driver returns `DATE`, `DATETIME`, `TIMESTAMP`, and `NEWDATE` columns as `[]byte` slices in MySQL wire format.
- **No time.Time conversion**: The `parseDateTime` function in [`utils.go`](https://github.com/go-sql-driver/mysql/blob/main/utils.go) is bypassed, eliminating parsing overhead and zero-date normalization.
- **Scanning requirements**: Destination variables must be `[]byte`, `string`, or `sql.RawBytes`; scanning into `time.Time` produces a conversion error.
- **Zero-date literal**: MySQL zero-dates (`0000-00-00`) are returned as literal byte strings rather than Go's zero `time.Time` value.

## Frequently Asked Questions

### What happens if I scan a DATE into time.Time with parseTime=false?

The scan operation fails with a conversion error. Because [`packets.go`](https://github.com/go-sql-driver/mysql/blob/main/packets.go) returns the column as `[]byte` when `parseTime=false`, the `database/sql` package cannot automatically convert that byte slice into a `time.Time` struct. You must scan into `[]byte` or `string` first, then manually parse the value.

### How does parseTime=false handle MySQL zero dates?

With `parseTime=false`, the driver does not invoke the zero-date detection logic in [`utils.go`](https://github.com/go-sql-driver/mysql/blob/main/utils.go). Instead, the literal byte string `"0000-00-00"` (for `DATE`) or `"0000-00-00 00:00:00"` (for `DATETIME`) is returned unchanged. This differs from `parseTime=true`, which maps these values to `time.Time{}`.

### Can I convert the raw bytes to time.Time manually?

Yes. When `parseTime=false`, you receive the date as a `[]byte` or `string` (e.g., `"2023-01-15 12:34:56"`). You can use `time.Parse("2006-01-02 15:04:05", string(rawBytes))` to convert it to `time.Time`. This allows custom location handling or alternative date layouts without driver-level configuration.

### Is parseTime=false faster than parseTime=true?

Generally, yes. Disabling `parseTime` avoids the overhead of `parseDateTime` in [`utils.go`](https://github.com/go-sql-driver/mysql/blob/main/utils.go), which performs string parsing, validation, and location-aware conversion. For high-throughput applications that do not need `time.Time` objects or that handle date parsing independently, `parseTime=false` reduces CPU usage per row fetched.