Skip to content

Set session timezone to UTC when loc is UTC and timezone undefined #1122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

felipecaputo
Copy link

@felipecaputo felipecaputo commented Jun 1, 2020

Description

Accord to the proposal at #1114, implemented a change that will set the database session timezone to UTC when loc == nil or locis UTC and the database time_zone is not set.

Checklist

  • Code compiles correctly
  • Created tests which fail without the change (if possible)
  • All tests passing
  • Extended the README / documentation, if necessary
  • Added myself / the copyright holder to the AUTHORS file

Added a validation when, loc is not defined OR is UTC to set
database session to use the UTC time zone, as proposed in go-sql-driver#114
Changed UTC to `+00:00` to avoid errors on setting timezone when the
SO doesn't have named timezones
@felipecaputo
Copy link
Author

In Mac tests are passing, but for Linux no. I'll boot my Linux PC later to try there and fix the problem

@breezewish
Copy link

breezewish commented Oct 10, 2021

I think this is a breaking change, as MySQL uses the session time zone to parse the time string. Example:

package main

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

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

func main() {
	dsn := mysql.NewConfig()
	dsn.Params = map[string]string{"time_zone": "'+08:00'"}
	dsn.ParseTime = true
	dsn.Loc = time.UTC
	dsn.User = "root"
	dsn.DBName = "test"

	db, err := sql.Open("mysql", dsn.FormatDSN())
	if err != nil {
		panic(err)
	}
	defer db.Close()

	_, err = db.Exec("DROP TABLE IF EXISTS foo")
	if err != nil {
		panic(err)
	}
	_, err = db.Exec("CREATE TABLE foo (c TIMESTAMP(6))")
	if err != nil {
		panic(err)
	}
	_, err = db.Exec("INSERT INTO foo VALUES ('2020-10-01 05:12:34')")
	if err != nil {
		panic(err)
	}

	var r float64
	err = db.QueryRow("SELECT UNIX_TIMESTAMP(c) FROM foo").Scan(&r)
	if err != nil {
		panic(err)
	}
	fmt.Println(int64(r))
}

If you change "time_zone": "'+08:00'" to something else like "time_zone": "'+00:00'", the output varies.

@felipecaputo
Copy link
Author

felipecaputo commented Oct 15, 2021

Hi @breeswish, I will get back into this (sorry to have forgotten) but when the session timezone is set, there are no changes (shouldn't be)

The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]

@methane
Copy link
Member

methane commented Oct 16, 2021

The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]

What happen if the application is relying on the default timezone of MySQL?

@breezewish
Copy link

breezewish commented Oct 16, 2021

The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]

I have the same concern as @methane . Consider this scenario:

a. The default timezone of MySQL is a local time zone. Let's take local time zone is +08:00 as an example, the MySQL session default timezone is +08:00 now.
b. The application uses go-mysql-driver contains the behavior:
Insert a timestamp by using the human readable form: MySQL will parse this human readable form using the default time zone (+08:00) and store its UTC time value.

Note: the user does not explicitly specify a timezone using the driver, but is relying on the default time zone.

c. Now, if the driver starts to change the time zone by default, e.g. changing to UTC, the next stored time value will be broken. The broken time value can be easily found by selecting using UNIX_TIMESTAMP() (which is not relying on the session time zone).

@felipecaputo
Copy link
Author

felipecaputo commented Oct 18, 2021

@methane @breeswish

This was what was happening with us, the database was -04:00 and we were not setting the session time zone, in database we had TIMESTAMP fields, with an example of 2021-10-19T20:00:00-0400, but when we get the date from the database, was loc was niland assumed UTC by default, we ended up with 2021-10-19T20:00:00Z as the session timezone and loc had different values [link to example]

The fact is that, if we had applications that doesn't set the session timezone and are treating data outside the driver, it can lead to a breaking change.

@methane methane closed this May 28, 2023
@methane
Copy link
Member

methane commented May 28, 2023

I think user should set time_zone explicitly if it is needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants