core/server/models/base/index.js
function sanitizeData(data) {
        var tableName = _.result(this.prototype, 'tableName'), date;

        _.each(data, (value, property) => {
            if (value !== null
                && schema.tables[tableName].hasOwnProperty(property)
                && schema.tables[tableName][property].type === 'dateTime'
                && typeof value === 'string'
            ) {
                date = new Date(value);

                // CASE: client sends `0000-00-00 00:00:00`
                if (isNaN(date)) {
                    throw new common.errors.ValidationError({
                        message: common.i18n.t('errors.models.base.invalidDate', {key: property}),
                        code: 'DATE_INVALID'
                    });
                }

                data[property] = moment(value).toDate();
            }

            if (this.prototype.relationships && this.prototype.relationships.indexOf(property) !== -1) {
                _.each(data[property], (relation, indexInArr) => {
                    _.each(relation, (value, relationProperty) => {
                        if (value !== null
                            && schema.tables[this.prototype.relationshipBelongsTo[property]].hasOwnProperty(relationProperty)
                            && schema.tables[this.prototype.relationshipBelongsTo[property]][relationProperty].type === 'dateTime'
                            && typeof value === 'string'
                        ) {
                            date = new Date(value);

                            // CASE: client sends `0000-00-00 00:00:00`
                            if (isNaN(date)) {
                                throw new common.errors.ValidationError({
                                    message: common.i18n.t('errors.models.base.invalidDate', {key: relationProperty}),
                                    code: 'DATE_INVALID'
                                });
                            }

                            data[property][indexInArr][relationProperty] = moment(value).toDate();
                        }
                    });
                });
            }
        });

        return data;
    }
function sanitizeData(data) {
        var tableName = _.result(this.prototype, 'tableName'), date;

        _.each(data, (value, property) => {
            if (value !== null
                && schema.tables[tableName].hasOwnProperty(property)
                && schema.tables[tableName][property].type === 'dateTime'
                && typeof value === 'string'
            ) {
                date = new Date(value);

                // CASE: client sends `0000-00-00 00:00:00`
                if (isNaN(date)) {
                    throw new common.errors.ValidationError({
                        message: common.i18n.t('errors.models.base.invalidDate', {key: property}),
                        code: 'DATE_INVALID'
                    });
                }

                data[property] = moment(value).toDate();
            }

            if (this.prototype.relationships && this.prototype.relationships.indexOf(property) !== -1) {
                _.each(data[property], (relation, indexInArr) => {
                    _.each(relation, (value, relationProperty) => {
                        if (value !== null
                            && schema.tables[this.prototype.relationshipBelongsTo[property]].hasOwnProperty(relationProperty)
                            && schema.tables[this.prototype.relationshipBelongsTo[property]][relationProperty].type === 'dateTime'
                            && typeof value === 'string'
                        ) {
                            date = new Date(value);

                            // CASE: client sends `0000-00-00 00:00:00`
                            if (isNaN(date)) {
                                throw new common.errors.ValidationError({
                                    message: common.i18n.t('errors.models.base.invalidDate', {key: relationProperty}),
                                    code: 'DATE_INVALID'
                                });
                            }

                            data[property][indexInArr][relationProperty] = moment(value).toDate();
                        }
                    });
                });
            }
        });

        return data;
    }
function sanitizeData ( data ) { var tableName = _ . result ( this . prototype , 'tableName' ) , date ; _ . each ( data , ( value , property ) => { if ( value !== null && schema . tables [ tableName ] . hasOwnProperty ( property ) && schema . tables [ tableName ] [ property ] . type === 'dateTime' && typeof value === 'string' ) { date = new Date ( value ) ; // CASE: client sends `0000-00-00 00:00:00` if ( isNaN ( date ) ) { throw new common . errors . ValidationError ( { message : common . i18n . t ( 'errors.models.base.invalidDate' , { key : property } ) , code : 'DATE_INVALID' } ) ; } data [ property ] = moment ( value ) . toDate ( ) ; } if ( this . prototype . relationships && this . prototype . relationships . indexOf ( property ) !== - 1 ) { _ . each ( data [ property ] , ( relation , indexInArr ) => { _ . each ( relation , ( value , relationProperty ) => { if ( value !== null && schema . tables [ this . prototype . relationshipBelongsTo [ property ] ] . hasOwnProperty ( relationProperty ) && schema . tables [ this . prototype . relationshipBelongsTo [ property ] ] [ relationProperty ] . type === 'dateTime' && typeof value === 'string' ) { date = new Date ( value ) ; // CASE: client sends `0000-00-00 00:00:00` if ( isNaN ( date ) ) { throw new common . errors . ValidationError ( { message : common . i18n . t ( 'errors.models.base.invalidDate' , { key : relationProperty } ) , code : 'DATE_INVALID' } ) ; } data [ property ] [ indexInArr ] [ relationProperty ] = moment ( value ) . toDate ( ) ; } } ) ; } ) ; } } ) ; return data ; }
`sanitizeData` ensures that client data is in the correct format for further operations.

Dates:
- client dates are sent as ISO 8601 format (moment(..).format())
- server dates are in JS Date format
>> when bookshelf fetches data from the database, all dates are in JS Dates
>> see `parse`
- Bookshelf updates the model with the new client data via the `set` function
- Bookshelf uses a simple `isEqual` function from lodash to detect real changes
- .previous(attr) and .get(attr) returns false obviously
- internally we use our `hasDateChanged` if we have to compare previous dates
- but Bookshelf is not in our control for this case

@IMPORTANT
Before the new client data get's inserted again, the dates get's re-transformed into
proper strings, see `format`.

@IMPORTANT
Sanitize relations.
sanitizeData ensures that client data is in the correct format for further operations .