orientechnologies / orientjs

The official fast, lightweight node.js client for OrientDB
http://orientdb.com
Other
326 stars 67 forks source link

Problem with date before the start of Gregorian Calendar #48

Open Ndrou opened 9 years ago

Ndrou commented 9 years ago

Hi,

I have a problem when inserting date before the start of the gregorian calendar (10-15-1582)

If i insert a date in OrientDb before 10-15-1582, the date returned on select does not match to the inserted.

If i insert a date in OrientDb after 10-15-1582, the date returned on select match to the inserted.

I have created a unit test if you want to see :

describe("Bug 330: Select date before gregorian calendar", function () {
    this.timeout(10 * 10000);
    var LIMIT = 5000;
    before(function () {
        return CREATE_TEST_DB(this, 'testdb_bug_330')
            .bind(this)
            .then(function () {
                return this.db.class.create('User', 'V');
            })
            .then(function (item) {
                this.class = item;
                return item.property.create([
                    {
                        name: 'firstname',
                        type: 'String'
                    },
                    {
                        name: 'birthDate',
                        type: 'datetime'
                    }
                ])
            })
            .then(function () {
                return this.db.query('CREATE VERTEX User SET firstname = :firstname, birthDate = :birthDate',
                    {
                        params: {
                            firstname: 'Robert',
                            birthDate: new Date("1200-11-11T00:00:00.000Z")
                        }
                    }
                );
            })
            .then(function () {
                return this.db.query('CREATE VERTEX User SET firstname = :firstname, birthDate = :birthDate',
                    {
                        params: {
                            firstname: 'Marcel',
                            birthDate: new Date("1582-10-15T00:00:00.000Z") // Start Gregorian calendar
                        }
                    }
                );
            })
            .then(function () {
                return this.db.query('CREATE VERTEX User SET firstname = :firstname, birthDate = :birthDate',
                    {
                        params: {
                            firstname: 'Andrew',
                            birthDate: new Date("1987-03-03T00:00:00.000Z")
                        }
                    }
                );
            })
    });
    after(function () {
        return DELETE_TEST_DB('testdb_bug_330');
    });

    it('should get the previously inserted date', function () {

        return this.db.query('SELECT FROM User WHERE firstname = :firstname',
            {
                params: {
                    firstname: 'Robert'
                }
            }
        ).then(function (result) {

                var expectedDate = new Date("1200-11-11T00:00:00.000Z");
                result[0].birthDate.should.be.eql(expectedDate);

            })

    });

    it('should get the previously inserted date', function () {

        return this.db.query('SELECT FROM User WHERE firstname = :firstname',
            {
                params: {
                    firstname: 'Marcel'
                }
            }
        ).then(function (result) {

                var expectedDate = new Date("1582-10-15T00:00:00.000Z");
                result[0].birthDate.should.be.eql(expectedDate);

            })

    });

    it('should get the previously inserted date', function () {

        return this.db.query('SELECT FROM User WHERE firstname = :firstname',
            {
                params: {
                    firstname: 'Andrew'
                }
            }
        ).then(function (result) {

                var expectedDate = new Date("1987-03-03T00:00:00.000Z");
                result[0].birthDate.should.be.eql(expectedDate);

            })

    });
});
Ndrou commented 9 years ago

If someone else have the same problem, below a temporary fix :

If you need to get date, get the date as string :

SELECT birthDate.format("yyyy-MM-dd HH:mm:ss:SSS Z", "UTC") as birthDate FROM User

And in javascript, reconstruct the date field :

var resultDate = new Date(result[0].birthDate);
lvca commented 9 years ago

Created your test case in Java and passes.

Ndrou commented 9 years ago

The LONG value of 1200-11-11T00:00:00.000Z in javascript is -24271660800000.

When i select this field with orientjs, the raw result equals -24271056000000

-24271660800000 = Sat, 11 Nov 1200 00:00:00 GMT
-24271056000000 = Sat, 18 Nov 1200 00:00:00 GMT

You should test the LONG value returned to the binary protocol.

wolf4ood commented 8 years ago

@Ndrou

the problem is

JavaScript

var expectedDate = new Date("1200-11-11T00:00:00.000Z");
console.log(expectedDate.getTime());
-24271660800000

Java

DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date d = format.parse("1200-11-11 00:00:00.000");
System.out.println(d.getTime());
-24271059600000
Ndrou commented 8 years ago

In the meantime, we have fixed the problem by storing dates as LONG.