diff --git a/package.json b/package.json index cb39e5db..b89e4eb8 100644 --- a/package.json +++ b/package.json @@ -49,13 +49,13 @@ "node": ">= 12.0.0" }, "dependencies": { + "dayjs": "^1.10.3", "debug": "^3.1.0", "deep-equal": "^2.0.5", "heredoc": "^1.3.1", "pluralize": "^7.0.0", "reflect-metadata": "^0.1.13", "sqlstring": "^2.3.0", - "strftime": "^0.10.0", "validator": "^13.5.2" }, "devDependencies": { @@ -65,7 +65,6 @@ "@journeyapps/sqlcipher": "^5.2.0", "@types/mocha": "^9.0.0", "@types/node": "^16.10.1", - "dayjs": "^1.10.3", "eslint": "^7.20.0", "eslint-plugin-no-only-tests": "^3.0.0", "expect.js": "^0.3.1", diff --git a/src/data_types.ts b/src/data_types.ts index e6cf382e..98d679a1 100644 --- a/src/data_types.ts +++ b/src/data_types.ts @@ -1,5 +1,6 @@ import Raw from './raw'; import util from 'util'; +import dayjs from 'dayjs'; const invokableFunc = require('./utils/invokable'); export enum LENGTH_VARIANTS { @@ -316,14 +317,13 @@ class DATE extends DataType { // @deprecated // vaguely standard date formats such as 2021-10-15 15:50:02,548 if (typeof value === 'string' && rDateFormat.test(value)) { - // 2021-10-15 15:50:02,548 => 2021-10-15T15:50:02,548, - // 2021-10-15 15:50:02 => 2021-10-15T15:50:02.000 - value = new Date(`${value.replace(' ', 'T').replace(',', '.')}`); + // 2021-10-15 15:50:02,548 => 2021-10-15 15:50:02.548, + value = dayjs(`${value.replace(',', '.')}`).toDate(); } // 1634611135776 // '2021-10-15T08:38:43.877Z' - if (!(value instanceof Date)) value = new Date((value as string)); + if (!(value instanceof Date)) value = dayjs((value as string)).toDate(); if (isNaN((value as any))) throw new Error(util.format('invalid date: %s', originValue)); return this._round(value); diff --git a/src/drivers/mysql/spellbook.js b/src/drivers/mysql/spellbook.js index 7b714559..9d4fc7e3 100644 --- a/src/drivers/mysql/spellbook.js +++ b/src/drivers/mysql/spellbook.js @@ -39,7 +39,7 @@ class MySQLSpellBook extends Spellbook { const { columnAttributes, primaryColumn } = Model; if (Array.isArray(updateOnDuplicate) && updateOnDuplicate.length) { - columns = updateOnDuplicate.map(column => (columnAttributes[column] && columnAttributes[column].columnName ) || column) + columns = updateOnDuplicate.map(column => (columnAttributes[column] && columnAttributes[column].columnName) || column) .filter(column => column !== primaryColumn); } else if (!columns.length) { columns = Object.values(columnAttributes).map(attribute => attribute.columnName).filter(column => column !== primaryColumn); @@ -80,7 +80,7 @@ class MySQLSpellBook extends Spellbook { /** * DELETE ... ORDER BY ...LIMIT - * @param {Spell} spell + * @param {Spell} spell */ formatDelete(spell) { const result = super.formatDelete(spell); diff --git a/src/drivers/sqlite/index.js b/src/drivers/sqlite/index.js index 0ac5793c..081fb8f3 100644 --- a/src/drivers/sqlite/index.js +++ b/src/drivers/sqlite/index.js @@ -1,6 +1,6 @@ 'use strict'; -const strftime = require('strftime'); +const dayjs = require('dayjs'); const { performance } = require('perf_hooks'); const AbstractDriver = require('../abstract'); @@ -46,7 +46,7 @@ class SqliteDriver extends AbstractDriver { if (values) { values = values.map(entry => { if (entry instanceof Date) { - return strftime('%Y-%m-%d %H:%M:%S.%L %:z', entry); + return dayjs(entry).format('YYYY-MM-DD HH:mm:ss.SSS Z'); } return entry; }); diff --git a/src/migrations.js b/src/migrations.js index 2143a835..3267bb04 100644 --- a/src/migrations.js +++ b/src/migrations.js @@ -1,8 +1,8 @@ 'use strict'; +const dayjs = require('dayjs'); const fs = require('fs').promises; const path = require('path'); -const strftime = require('strftime'); async function loadTasks(dir) { const entries = await fs.readdir(dir, { withFileTypes: true }); @@ -61,7 +61,7 @@ async function rollback(step = 1) { async function createMigrationFile(name) { const { migrations: dir } = this.options; - const timestamp = strftime('%Y%m%d%H%M%S'); + const timestamp = dayjs().format('YYYYMMDDHHmmss'); const fpath = path.join(dir, `${timestamp}-${name}.js`); await fs.writeFile(fpath, `'use strict'; diff --git a/test/integration/custom.test.js b/test/integration/custom.test.js index 43cf9fac..65f14e51 100644 --- a/test/integration/custom.test.js +++ b/test/integration/custom.test.js @@ -58,8 +58,8 @@ class MySpellbook extends SqliteDriver.Spellbook { obj[escapeId(Model.unalias(key))] = spell.sets[key]; return obj; }, values); - - let whereArgs = []; + + const whereArgs = []; let whereClause = ''; if (whereConditions.length > 0) { for (const condition of whereConditions) collectLiteral(spell, condition, whereArgs); @@ -77,7 +77,7 @@ class MySpellbook extends SqliteDriver.Spellbook { const { Model, whereConditions } = spell; const { escapeId } = Model.driver; const table = escapeId(spell.table.value); - let whereArgs = []; + const whereArgs = []; let whereClause = ''; if (whereConditions.length > 0) { for (const condition of whereConditions) collectLiteral(spell, condition, whereArgs); @@ -94,7 +94,7 @@ class MySpellbook extends SqliteDriver.Spellbook { const { Model, sets } = spell; const { escapeId } = Model.driver; const table = escapeId(spell.table.value); - let values = {}; + const values = {}; const { shardingKey } = Model; if (shardingKey && sets[shardingKey] == null) { diff --git a/test/integration/mysql.test.js b/test/integration/mysql.test.js index f6e8fd0a..af9989d8 100644 --- a/test/integration/mysql.test.js +++ b/test/integration/mysql.test.js @@ -2,7 +2,7 @@ const assert = require('assert').strict; const path = require('path'); -const strftime = require('strftime'); +const dayjs = require('dayjs'); const { connect } = require('../..'); @@ -91,7 +91,7 @@ describe('=> Data types (mysql)', function() { birthday: new Date(2021, 5, 26), sex: 'M', }); - assert.equal(strftime('%Y-%m-%d', user.birthday), '2021-06-26'); + assert.equal(dayjs(user.birthday).format('YYYY-MM-DD'), '2021-06-26'); }); it('CHAR', async function() { diff --git a/test/integration/suite/data_types.test.js b/test/integration/suite/data_types.test.js index 66a4507c..b27d1b82 100644 --- a/test/integration/suite/data_types.test.js +++ b/test/integration/suite/data_types.test.js @@ -1,7 +1,7 @@ 'use strict'; const assert = require('assert').strict; -const strftime = require('strftime'); +const dayjs = require('dayjs'); const { Bone, DataTypes } = require('../../..'); const { INTEGER, STRING, DATE, DATEONLY, TEXT, BOOLEAN, JSON, JSONB, BIGINT } = DataTypes; @@ -270,7 +270,7 @@ describe('=> Data types - DATE', function() { }); await assert.doesNotReject(async function() { - const result = await Note.where({ createdAt: strftime('%Y-%m-%d %H:%M:%S,%L', date) }); + const result = await Note.where({ createdAt: dayjs(date).format('YYYY-MM-DD HH:mm:ss,SSS') }); assert.equal(result.length, 1); }); @@ -319,7 +319,7 @@ describe('=> Data types - DATEONLY', function() { const date = new Date('2021-10-15T08:38:43.877Z'); const note = await Note.create({ createdAt: date }); await note.reload(); - assert.equal(strftime('%Y-%m-%d', note.createdAt), '2021-10-15'); + assert.equal(dayjs(note.createdAt).format('YYYY-MM-DD'), '2021-10-15'); await assert.doesNotReject(async function() { const result = await Note.where({ createdAt: date }); diff --git a/test/integration/suite/migrations.test.js b/test/integration/suite/migrations.test.js index 65f2a86d..ad0de74b 100644 --- a/test/integration/suite/migrations.test.js +++ b/test/integration/suite/migrations.test.js @@ -3,7 +3,7 @@ const assert = require('assert').strict; const fs = require('fs').promises; const path = require('path'); -const strftime = require('strftime'); +const dayjs = require('dayjs'); const Realm = require('../../..'); const Logger = require('../../../src/drivers/abstract/logger'); @@ -15,7 +15,7 @@ const migrations = path.join(__dirname, '../migrations'); // class Topic extends Realm.Bone {} async function createTopics() { - const name = `${strftime('%Y%m%d%H%M%S')}-create-topics.js`; + const name = `${dayjs().format('YYYYMMDDHHmmss')}-create-topics.js`; const fpath = path.join(migrations, name); await fs.writeFile(fpath, `'use strict'; diff --git a/test/unit/drivers/sqlite/index.test.js b/test/unit/drivers/sqlite/index.test.js index 66effc84..8ca1f0b4 100644 --- a/test/unit/drivers/sqlite/index.test.js +++ b/test/unit/drivers/sqlite/index.test.js @@ -2,7 +2,7 @@ const assert = require('assert').strict; const path = require('path'); -const strftime = require('strftime'); +const dayjs = require('dayjs'); const { heresql } = require('../../../../src/utils/string'); const SqliteDriver = require('../../../../src/drivers/sqlite'); @@ -169,7 +169,7 @@ describe('=> SQLite driver.query()', () => { } = await driver.query(heresql(` SELECT datetime(created_at, 'localtime') AS created_at FROM notes `)); - assert.equal(created_at, strftime('%Y-%m-%d %H:%M:%S', createdAt)); + assert.equal(created_at, dayjs(createdAt).format('YYYY-MM-DD HH:mm:ss')); }); it('should handle boolean correctly', async () => { diff --git a/test/unit/expr_formatter.test.js b/test/unit/expr_formatter.test.js index 6dd4addc..a9e5de74 100644 --- a/test/unit/expr_formatter.test.js +++ b/test/unit/expr_formatter.test.js @@ -1,7 +1,7 @@ 'use strict'; const assert = require('assert').strict; -const strftime = require('strftime'); +const dayjs = require('dayjs'); const { connect, Bone } = require('../..'); describe('=> formatExpr', function() { @@ -35,7 +35,7 @@ describe('=> formatExpr', function() { it('should cast date with precision set in database', async function() { // users.birthday stores DATE without specific hours or so const today = new Date(); - const formatted = strftime('%Y-%m-%d', today); + const formatted = dayjs(today).format('YYYY-MM-DD'); assert.equal( User.where({ birthday: today }).toSqlString(), "SELECT * FROM `users` WHERE `birthday` = '" + formatted + " 00:00:00.000'" diff --git a/test/unit/spell.test.js b/test/unit/spell.test.js index cac79a48..b4f08877 100644 --- a/test/unit/spell.test.js +++ b/test/unit/spell.test.js @@ -469,6 +469,13 @@ describe('=> Spell', function() { ); }); + it('where date', function() { + assert.equal( + Post.where('createdAt > ?', '2022-11-03').toString(), + "SELECT * FROM `articles` WHERE `gmt_create` > '2022-11-03 00:00:00.000' AND `gmt_deleted` IS NULL" + ); + }); + it('where compound string conditions', function() { assert.equal( Post.where('title like "Arch%" or (title = "New Post" || title = "Skeleton King")').toString(), @@ -623,8 +630,8 @@ describe('=> Spell', function() { it('order by string with multiple condition', () => { assert.equal( - Post.order('id asc, gmt_created desc').toString(), - 'SELECT * FROM `articles` WHERE `gmt_deleted` IS NULL ORDER BY `id`, `gmt_created` DESC' + Post.order('id asc, gmt_create desc').toString(), + 'SELECT * FROM `articles` WHERE `gmt_deleted` IS NULL ORDER BY `id`, `gmt_create` DESC' ); });