Hola, estoy usando Sequelize con una base de datos de Postgres
Así que estoy tratando de formatear la fecha en las columnas de la secuela createdAt y updatedAt como YYYY-MM-DD HH:mm:ss Además de mantener las columnas como snake_case no camelcase para que se created_at y se updated_at ¿Cómo puedo lograr esto? He probado lo siguiente:
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: moment.utc().format('YYYY-MM-DD HH:mm:ss'), field: 'created_at' },o
createdAt: { type: DataTypes.DATE, defaultValue: sequelize.NOW, set(value) { return value.toISOString().replace(/\..+/g, '') // coming 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', },no funciona y me sale este 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 objectAquí está toda la tabla definida anteriormente, es lo que he señalado con lo que necesito ayuda
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 });Gracias
Hoy Sequelize docs no funciona aquí hay un archivo web para ello
https://web.archive.org/web/20200731154157/http://sequelize.org/master/index.html
Según tengo entendido, su pregunta contiene algunas subpreguntas:
Aquí hay un ejemplo de trabajo (con los requisitos mencionados anteriormente) que acabo de recibir:
Tener una migración de secuela como esta:
'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'); } };Tener un modelo de secuela como este:
'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' }); };No olvide cambiar el nombre de su tabla según sus necesidades, aquí está "elementos".
Parece que hay un problema publicado en github con la propiedad "subrayada" de secuela. De todos modos funcionó para mí, porque hay un pequeño truco con otras propiedades, así que hazlo y creo que debería funcionar (la versión Sequelize para mí fue "^ 5.22.3").
Fuentes que he usado:
Siéntase libre de editar y optimizar si lo necesita (hice algunas ediciones pequeñas en el método get () para obtener el formato exacto que desea, de todos modos prefiero usar el momento como acceso a la columna).
Solución
En cuanto a lo anterior, el método get() solo devolverá el valor formateado al cliente, pero no lo guardará en la base de datos. He encontrado tres opciones para guardarlo en la base de datos, por lo tanto, la solución para este problema para cualquiera que experimente algo similar.
1. Primera opción
Dentro de node_modules/sequelize/lib/data-types.js
Tenemos que modificar el siguiente código.
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. Segunda Opción
Si no toca su carpeta node_modules y no le gusta la opción 1, una solución algo mejor sería hacer lo que hizo en la opción 1 pero en su propio archivo db.js:
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;Así que estas dos opciones son más como una forma global de hacerlo, por lo que el formato será para todos sus modelos.
3. Tercera Opción
La opción final es hacerlo para cada modelo individual usando ganchos
Ejemplo:
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, ''); } }, })