Typeorm: may i know is the feature to convert date to UTC before saving to mysql is removed since 0.1.18. It was working fine in 0.1.17. I tried all subsequent version from 0.1.18 onward and none of it is working.

Created on 23 Apr 2018  Β·  41Comments  Β·  Source: typeorm/typeorm

may i know is the feature to convert date to UTC before saving to mysql is removed since 0.1.18. It was working fine in 0.1.17. I tried all subsequent version from 0.1.18 onward and none of it is working.

Issue type:

[βœ”] question
[ βœ”] bug report
[ ] feature request
[ ] documentation issue

Database system/driver:

[ ] cordova
[ ] mongodb
[ ] mssql
[βœ” ] mysql / mariadb
[ ] oracle
[ ] postgres
[ ] sqlite
[ ] sqljs
[ ] react-native

TypeORM version:

[ ] latest
[ ] @next
[ βœ”] 0.1.17 (or put your version here)

link to reference issue #976

Steps to reproduce or a small repository showing the problem:

correct UTC
Mysql interface : 2018-01-31 16:00:00 --> correct UTC
em.query('select * table_name') : 2018-01-31T08:00:00.000Z --> wrong???
em.findOne() : 2018-01-31T16:00:00.000Z, -->correct
em.createQueryBuilder() : 2018-01-31T16:00:00.000Z -->correct

0.1.19

with typeorm option timezone: 'Z'
Code: new Date('2018-02-01T00:00:00+08:00');
logging Insert : 2018-01-31T16:00:00.000Z --> correct UTC
After em.save() return 2018-01-31T16:00:00.000Z ---> correct UTC
Mysql interface: 2018-01-31 16:00:00 --> correct UTC
em.query('select * table_name') : 2018-01-31T08:00:00.000. ---> incorrect
em.findOne(): 2018-01-31T08:00:00.000Z, ---> incorrect
em.createQueryBuilder() : 2018-01-31T08:00:00.000Z --> incorrect

i created a small test case, can you help to run it and let's compare output

@Entity()
export class TestMysql {
  @PrimaryGeneratedColumn() id: number;

  @Column({ name: 'date_test', nullable: false })
  dateTest: Date;
}

        await getManager('main').transaction(async entityManager => {
          const testMysql = new TestMysql();
          testMysql['dateTest'] = new Date('2018-02-01 00:00:00+08');
          const saveResult = await entityManager.save(TestMysql, testMysql);
          console.log('-------saveResult-------');
          console.log(saveResult);

          const queryResult = await entityManager.query(
            `select * from test_mysql where id=${saveResult['id']}`
          );
          console.log('-------queryResult-------');
          console.log(queryResult);

          const findOneResult = await entityManager.findOne(TestMysql, { id: saveResult['id'] });
          console.log('-------findOneResult-------');
          console.log(findOneResult);

          const createQueryBuilderResult = await entityManager
            .createQueryBuilder(TestMysql, 'testMysql')
            .where({ id: saveResult['id'] })
            .getMany();
          console.log('-------createQueryBuilderResult-------');
          console.log(createQueryBuilderResult);
        });

0.1.17 without typeorm timezone option
-------saveResult-------
TestMysql { dateTest: 2018-01-31T16:00:00.000Z, id: 2 }
executing query: select * from test_mysql where id=2
-------queryResult-------
[ TextRow { id: 2, date_test: 2018-01-31T08:00:00.000Z } ] // not suppose to be this result ???
executing query: SELECT TestMysql.id AS TestMysql_id, TestMysql.date_test AS TestMysql_date_test FROM test_mysql TestMysql WHERE TestMysql.id=? -- PARAMETERS: [2]
-------findOneResult-------
TestMysql { id: 2, dateTest: 2018-01-31T16:00:00.000Z } //correct
executing query: SELECT testMysql.id AS testMysql_id, testMysql.date_test AS testMysql_date_test FROM test_mysql testMysql WHERE testMysql.id=? -- PARAMETERS: [2]
-------createQueryBuilderResult-------
[ TestMysql { id: 2, dateTest: 2018-01-31T16:00:00.000Z } ] //correct

0.1.19 with typeorm timezone option 'Z'
-------saveResult-------
TestMysql { dateTest: 2018-01-31T16:00:00.000Z, id: 3 }
executing query: select * from test_mysql where id=3
-------queryResult-------
[ TextRow { id: 3, date_test: 2018-01-31T08:00:00.000Z } ] //incorrect
executing query: SELECT TestMysql.id AS TestMysql_id, TestMysql.date_test AS TestMysql_date_test FROM test_mysql TestMysql WHERE TestMysql.id=? -- PARAMETERS: [3]
-------findOneResult-------
TestMysql { id: 3, dateTest: 2018-01-31T08:00:00.000Z } //incorrect
executing query: SELECT testMysql.id AS testMysql_id, testMysql.date_test AS testMysql_date_test FROM test_mysql testMysql WHERE testMysql.id=? -- PARAMETERS: [3]
-------createQueryBuilderResult-------
[ TestMysql { id: 3, dateTest: 2018-01-31T08:00:00.000Z } ] //incorrect
executing query: COMMIT

0.1.19 without typeorm timezone option . (all output are correct)
-------saveResult-------
TestMysql { dateTest: 2018-01-31T16:00:00.000Z, id: 3 }
executing query: select * from test_mysql where id=3
-------queryResult-------
[ TextRow { id: 3, date_test: 2018-01-31T16:00:00.000Z } ] //correct
executing query: SELECT TestMysql.id AS TestMysql_id, TestMysql.date_test AS TestMysql_date_test FROM test_mysql TestMysql WHERE TestMysql.id=? -- PARAMETERS: [3]
-------findOneResult-------
TestMysql { id: 3, dateTest: 2018-01-31T16:00:00.000Z } //correct
executing query: SELECT testMysql.id AS testMysql_id, testMysql.date_test AS testMysql_date_test FROM test_mysql testMysql WHERE testMysql.id=? -- PARAMETERS: [3]
-------createQueryBuilderResult-------
[ TestMysql { id: 3, dateTest: 2018-01-31T16:00:00.000Z } ] //correct
the last test outputs are correct, but, in mysql interface, it is saved as 2018-02-01 00:00:00 instead of UCT

0.1.17 - without timezone config

-------saveResult-------
TestMysql { id: 4, dateTest: 2018-01-31T16:00:00.000Z }
executing query:  select * from test_mysql where id=4
-------queryResult-------
[ TextRow { id: 4, date_test: 2018-01-31T15:00:00.000Z } ]
executing query:  SELECT `TestMysql`.`id` AS `TestMysql_id`, `TestMysql`.`date_test` AS `TestMysql_date_test` FROM `test_mysql` `TestMysql` WHERE `TestMysql`.`id`=? -- PARAMETERS: [4]
-------findOneResult-------
TestMysql { id: 4, dateTest: 2018-01-31T16:00:00.000Z }
executing query:  SELECT `testMysql`.`id` AS `testMysql_id`, `testMysql`.`date_test` AS `testMysql_date_test` FROM `test_mysql` `testMysql` WHERE `testMysql`.`id`=? -- PARAMETERS: [4]
-------createQueryBuilderResult-------
[ TestMysql { id: 4, dateTest: 2018-01-31T16:00:00.000Z } ]
executing query:  COMMIT

0.1.19 - with timezone config 'Z'

-------saveResult-------
TestMysql { id: 6, dateTest: 2018-01-31T16:00:00.000Z }
executing query:  select * from test_mysql where id=6
-------queryResult-------
[ TextRow { id: 6, date_test: 2018-01-31T15:00:00.000Z } ]
executing query:  SELECT `TestMysql`.`id` AS `TestMysql_id`, `TestMysql`.`date_test` AS `TestMysql_date_test` FROM `test_mysql` `TestMysql` WHERE `TestMysql`.`id`=? -- PARAMETERS: [6]
-------findOneResult-------
TestMysql { id: 6, dateTest: 2018-01-31T15:00:00.000Z }
executing query:  SELECT `testMysql`.`id` AS `testMysql_id`, `testMysql`.`date_test` AS `testMysql_date_test` FROM `test_mysql` `testMysql` WHERE `testMysql`.`id`=? -- PARAMETERS: [6]
-------createQueryBuilderResult-------
[ TestMysql { id: 6, dateTest: 2018-01-31T15:00:00.000Z } ]
executing query:  COMMIT

0.1.19 - without timezone config

-------saveResult-------
TestMysql { id: 5, dateTest: 2018-01-31T16:00:00.000Z }
executing query:  select * from test_mysql where id=5
-------queryResult-------
[ TextRow { id: 5, date_test: 2018-01-31T16:00:00.000Z } ]
executing query:  SELECT `TestMysql`.`id` AS `TestMysql_id`, `TestMysql`.`date_test` AS `TestMysql_date_test` FROM `test_mysql` `TestMysql` WHERE `TestMysql`.`id`=? -- PARAMETERS: [5]
-------findOneResult-------
TestMysql { id: 5, dateTest: 2018-01-31T16:00:00.000Z }
executing query:  SELECT `testMysql`.`id` AS `testMysql_id`, `testMysql`.`date_test` AS `testMysql_date_test` FROM `test_mysql` `testMysql` WHERE `testMysql`.`id`=? -- PARAMETERS: [5]
-------createQueryBuilderResult-------
[ TestMysql { id: 5, dateTest: 2018-01-31T16:00:00.000Z } ]
executing query:  COMMIT

for me it's the same, mysql stores 2018-01-31 17:00:00.
but other than that it looks like it should work for you.

of course when you work in the database directly you will need to convert the timezone yourself.
e.g.:

SELECT id, date_test, CONVERT_TZ(date_test, '+8:00', 'UTC') FROM  test_mysql;

for your last case 0.1.19 - without timezone config , Aren't it not suppose to save in mysql as 2018-01-31 17:00:00 ? It should be stored in mysql as UTC right?

ok, I think I know what's causing the difference. even on my side I had results that diverted from prior tests.
I was trying your mysql driver mysql2 and since then things stopped producing correct results.
try to remove mysql2, install mysql and set the timezone option to +0.

this should at least give you correct results with typeorm and on the database side as well.
once we've established that deciding on the right mysql driver will be a different topic altogether.

looks like there is an easy fix for using mysql2.
mysql2 doesn't have a timezone setting in the connection config but it respects the TZ environment setting.

try this:

TZ=UTC  <your node command>

i did many round of tests. Below is the minimum changes that required to get it work on 0.1.19 onward
process.env.TZ=UTC
verified it saves in mysql as UTC and retrieve as UTC perfectly. No need to add tyeporm option timezone.

great, I'm glad it finally works for you. πŸŽ‰
to sum it up for others that might have the same issue there are 2 solutions based on the underlying mysql driver in use:

1) with mysql:

set timezone option in typeorm to +0

2) with mysql2:

run the node process with the timezone environment variable TZ=UTC

I think you can close the issue now

@chriskalmar thank you very much for your help!

@pleerock happy to help πŸ˜ƒ

@chriskalmar OMG thanks a lot.

@chriskalmar I actually faced this issue as well haha. So, solution is to add process.env.TZ = "UTC"; to resolve this issue and it works on any driver, am I right? If yes then probably we need to put more information in the docs about this, what do you think?

@pleerock well, this is only mysql related, so it would make sense to mention both methods (timezone option and process.env.TZ) nearby the mysql connection docs.

I work most of the time with postgres and there I don't need to set any of those options. Postgres has a great timezone support built in and it works out of the box.
So it's not a general setting for all databases.

Maybe the best place to put it is something like Advanced Topics -> Timezone support.

I also work with posgres and without process.env.TZ set to UTC it creates wrong dates (not wrong, it just treats dates read from your database as dates in a local timezone)

What datatype are you using? timestamp with time zone or another one?
Because with timestamp with time zone it's still UTC.
I'm using a pretty standard postgres docker container (which is set to UTC by default). I moved it to another timezone and still everything get stored correctly in UTC. When fetching data I get the expected result too.
Did you send the date in full timezone notation? (e.g. 2018-05-08 12:00:00+2)

I have 0.2.18 version and setting process.env.TZ to UTC does not help

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adrianhara picture adrianhara  Β·  49Comments

nealdyrkacz picture nealdyrkacz  Β·  48Comments

leoperria picture leoperria  Β·  37Comments

pleerock picture pleerock  Β·  135Comments

trixden picture trixden  Β·  50Comments