最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Sequelize How do you format date to YYYY-MM-DD HH:mm:ss and keep the columns as snake case - Stack Overflow

programmeradmin0浏览0评论

Hi I am using Sequelize with a Postgres Database

So I am trying to format date on the sequelize createdAt and updatedAt columns as YYYY-MM-DD HH:mm:ss As well as keeping the columns as snake_case not camelcase so they would be created_at and updated_atHow can I achieve this? I have tried the following:

    createdAt: {
      type: DataTypes.DATE,
      allowNull: false,
      defaultValue: moment.utc().format('YYYY-MM-DD HH:mm:ss'),
      field: 'created_at'
    },

or

    createdAt: {
      type: DataTypes.DATE,
      defaultValue: sequelize.NOW,
      set(value) {
        return value.toISOString().replace(/\..+/g, '')
// ing in the db as 2021-10-31 01:34:48.81+00 so wanted to remove evrything after the dot
      },
      name: 'createdAt',
      field: 'created_at',
    },

Is not working and I am getting this error

          throw new Error(`Value for "${key}" option must be a string or a boolean, got ${typeof this.options[key]}`);
          ^

Error: Value for "createdAt" option must be a string or a boolean, got object

Here is the whole table defined above is what I have pinpointed which I need help with

  const Supplier = sequelize.define('Supplier', {
    id: {
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      allowNull: false,
      primaryKey: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        len: [1, 50]
      }
    },
    description: {
      type: DataTypes.STRING,
      allowNull: true,
    },
  }, {
    tableName: 'suppliers',
    timestamps: true,
    createdAt: {
      type: DataTypes.DATE,
      defaultValue: sequelize.NOW,
      set(value) {
        return value.toISOString().replace(/\..+/g, '')
      },
      name: 'createdAt',
      field: 'created_at',
    },
    updatedAt: {
      type: DataTypes.DATE,
      defaultValue: sequelize.NOW,
      set(value) {
        return value.toISOString().replace(/\..+/g, '')
      },
      field: 'updated_at',
    },
    // freezeTableName: true
    // paranoid: true
  });

Thanks

Today Sequelize docs is not working here is a webarchive's for it

://sequelize/master/index.html

Hi I am using Sequelize with a Postgres Database

So I am trying to format date on the sequelize createdAt and updatedAt columns as YYYY-MM-DD HH:mm:ss As well as keeping the columns as snake_case not camelcase so they would be created_at and updated_atHow can I achieve this? I have tried the following:

    createdAt: {
      type: DataTypes.DATE,
      allowNull: false,
      defaultValue: moment.utc().format('YYYY-MM-DD HH:mm:ss'),
      field: 'created_at'
    },

or

    createdAt: {
      type: DataTypes.DATE,
      defaultValue: sequelize.NOW,
      set(value) {
        return value.toISOString().replace(/\..+/g, '')
// ing in the db as 2021-10-31 01:34:48.81+00 so wanted to remove evrything after the dot
      },
      name: 'createdAt',
      field: 'created_at',
    },

Is not working and I am getting this error

          throw new Error(`Value for "${key}" option must be a string or a boolean, got ${typeof this.options[key]}`);
          ^

Error: Value for "createdAt" option must be a string or a boolean, got object

Here is the whole table defined above is what I have pinpointed which I need help with

  const Supplier = sequelize.define('Supplier', {
    id: {
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      allowNull: false,
      primaryKey: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        len: [1, 50]
      }
    },
    description: {
      type: DataTypes.STRING,
      allowNull: true,
    },
  }, {
    tableName: 'suppliers',
    timestamps: true,
    createdAt: {
      type: DataTypes.DATE,
      defaultValue: sequelize.NOW,
      set(value) {
        return value.toISOString().replace(/\..+/g, '')
      },
      name: 'createdAt',
      field: 'created_at',
    },
    updatedAt: {
      type: DataTypes.DATE,
      defaultValue: sequelize.NOW,
      set(value) {
        return value.toISOString().replace(/\..+/g, '')
      },
      field: 'updated_at',
    },
    // freezeTableName: true
    // paranoid: true
  });

Thanks

Today Sequelize docs is not working here is a webarchive's for it

https://web.archive/web/20200731154157/http://sequelize/master/index.html

Share edited Oct 31, 2021 at 3:50 Mohamed asked Oct 31, 2021 at 1:01 MohamedMohamed 4692 gold badges5 silver badges18 bronze badges 3
  • The error says createdAt expects a string or a bool, and the code looks like it assigns an object createdAt: {...} – danh Commented Oct 31, 2021 at 1:53
  • How can I be specific in making it a string and formatted as YYYY-MM-DD HH:mm:ss and keeping the column as snake case. I know for instance if I did: createdAt: 'created_at', as stated on their docs I am making the column as snake case so my other goal I have is formatting it as I have stated without the milliseconds in the DB so how can I do that? @danh – Mohamed Commented Oct 31, 2021 at 1:59
  • 1 I just did some edits in the "get()" method for getting the exact format as you want, so it's ready now. Also it would be nice if you'll add the "postgres" tag under your question as well as the "date" type is necessary here. – boolfalse Commented Oct 31, 2021 at 3:42
Add a ment  | 

2 Answers 2

Reset to default 1

As I understand your question contains some subquetions:

  • Sequelize table column underscored names;
  • Sequelize date format;
  • Usage without moment;

Here's some working example (with requirements mentioned above) I've just got:

Have a sequelize migration like this:

'use strict';

module.exports = {
    up: (queryInterface, Sequelize) => {
        return queryInterface.createTable('items', {
            // ...
            created_at: {
                allowNull: false,
                type: Sequelize.DATE
            },
            // ...
        });
    },
    down: (queryInterface, Sequelize) => {
        return queryInterface.dropTable('items');
    }
};

Have a sequelize model like this:

'use strict';

// WITH moment
// const moment = require('moment');

module.exports = (sequelize, DataTypes) => {
    // const now = new Date();
    return sequelize.define('Item', {
        // ...
        created_at: {
            allowNull: false,
            // defaultValue: now,
            type: DataTypes.DATE,
            get() {
                // 1. WITHOUT moment
                const date = new Date(`${this.dataValues.created_at}`);
                return `${date.toISOString().split('T')[0]} ${date.toLocaleTimeString([], {month: '2-digit', timeStyle: 'medium', hour12: false})}`;
                
                // 2. WITHOUT moment (another solution)
                // const parts = date.toISOString().split('T');
                // return `${parts[0]} ${parts[1].substring(0, 8)}`;
                
                // 3. WITH moment
                // return moment(this.dataValues.created_at).format('D MM YYYY HH:mm:ss'); // 'D MMM YYYY, LT'
            }
        },
        // ...
    }, {
        tableName: 'items',
        freezeTableName: true,
        // underscored: true,
        timestamps: false,
        charset: 'utf8',
        collate: 'utf8_general_ci'
    });
};

Don't forget to rename your table name for your needs, here is "items".

Seems there is an issue posted on github with sequelize "underscored" property. Anyway it worked for me, cuz there is a small trick with other properties, so just do like that and I believe it should work (Sequelize version for me was "^5.22.3").

Sources I've used:

  • date formatting with/without Moment.js
  • JavaScript Date toLocaleString()
  • How to format a JavaScript date
  • Javascript add leading zeroes to date
  • How do I use .toLocaleTimeString() without displaying seconds?

Feel free to edit and optimize if you need (I did some small edits in the get() method for getting the exact format as you want, anyway I prefer to use moment as a column accessor).

Solution

As for above the get() method will only return the value as formatted to the client but it wont save it to the database. I have found three options to make it save to the database thus the solution for this issue for anyone experiencing something similar.

1. First Option

Inside the node_modules/sequelize/lib/data-types.js

We have to modify the following code

DATE.prototype._stringify = function _stringify(date, options) {
  date = this._applyTimezone(date, options);

  // Z here means current timezone, _not_ UTC
  // return date.format('YYYY-MM-DD HH:mm:ss.SSS Z');// from this to the below code
  return date.format('YYYY-MM-DD HH:mm:ss.SSS'); // to this
};

2. Second Option

If you don't to touch your node_modules folder and do not like option 1, than a somewhat better solution would be to do what you did at option 1 but in your own db.js file:

const { Sequelize } = require('sequelize');
const { DB } = require('../config');

// Override timezone formatting by requiring the Sequelize and doing it here instead
Sequelize.DATE.prototype._stringify = function _stringify(date, options) {
  date = this._applyTimezone(date, options);

  // Z here means current timezone, _not_ UTC
  // return date.format('YYYY-MM-DD HH:mm:ss.SSS Z');
  return date.format('YYYY-MM-DD HH:mm:ss Z');
};

const db = new Sequelize(`${DB.DIALECT}://${DB.USER}:${DB.PASS}@${DB.HOST}:${DB.PORT}/${DB.DB}`, {
  logging: false
})

module.exports = db;

So this two option is more like global way off doing it so the format will be for all your models.

3. Third Option

Final option is to do it for each single models by using hooks

Example:

const Supplier = sequelize.define('Supplier', {
// col attributes 
}, {
    tableName: 'suppliers',
    timestamps: true,
    createdAt: 'created_at',
    updatedAt: 'updated_at',
    hooks : {
      beforeCreate : (record, options) => {
          record.dataValues.created_at = new Date().toISOString().replace(/T/, ' ').replace(/\..+/g, '');
          record.dataValues.updated_at = new Date().toISOString().replace(/T/, ' ').replace(/\..+/g, '');
      },
      beforeUpdate : (record, options) => {
          record.dataValues.updated_at = new Date().toISOString().replace(/T/, ' ').replace(/\..+/g, '');
      }
    },
})

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论