Permalink
Browse files

Fixed: Dates before 1970 with time of midnight incorrectly inserted

This is especially onerous because the default time for a date is midnight.

Tests have been added to verify that dates with a time of midnight are
inserted and retrieved correctly.

Fixes #85
Fixes #103
  • Loading branch information...
1 parent 2850e48 commit f7d228f03d869c0701a54f885a7671c5dfc00058 @jkint jkint committed Jan 12, 2013
Showing with 103 additions and 8 deletions.
  1. +10 −8 src/Column.cpp
  2. +93 −0 test/params.js
View
@@ -113,9 +113,9 @@ int64_t TimestampColumn::YearFromDay( int64_t& day )
}
}
- if( day <= 0 ) {
+ if( day < 0 ) {
--year;
- day += days_in_year - 1;
+ day += days_in_year;
}
}
@@ -126,7 +126,7 @@ int64_t TimestampColumn::YearFromDay( int64_t& day )
// since Jan 1, 1970. Dates before 1970 are represented as negative numbers.
void TimestampColumn::DateFromMilliseconds( SQL_SS_TIMESTAMPOFFSET_STRUCT& date )
{
- static const int64_t days_in_months[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ static const int64_t days_in_months[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static const int64_t leap_days_in_months[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int64_t const* start_days = days_in_months;
@@ -141,6 +141,13 @@ void TimestampColumn::DateFromMilliseconds( SQL_SS_TIMESTAMPOFFSET_STRUCT& date
start_days = leap_days_in_months;
}
+ // calculate time portion of the timestamp
+ int64_t time = static_cast<int64_t>( milliseconds ) % MS_PER_DAY;
+ if( time < 0 ) {
+ time = MS_PER_DAY + time;
+ --day;
+ }
+
int64_t month = 0;
while( day >= start_days[ month ] ) {
day -= start_days[ month ];
@@ -153,11 +160,6 @@ void TimestampColumn::DateFromMilliseconds( SQL_SS_TIMESTAMPOFFSET_STRUCT& date
date.month = static_cast<SQLUSMALLINT>( month + 1 );
date.day = static_cast<SQLUSMALLINT>( day + 1 );
- // calculate time portion of the timestamp
- int64_t time = static_cast<int64_t>( milliseconds ) % MS_PER_DAY;
- if( time < 0 ) {
- time = MS_PER_DAY + time;
- }
// SQL Server has 100 nanosecond resolution, so we adjust the milliseconds to high bits
date.hour = time / MS_PER_HOUR;
date.minute = (time % MS_PER_HOUR) / MS_PER_MINUTE;
View
@@ -588,4 +588,97 @@ suite( 'params', function() {
test_done );
});
+ // verify fix for a bug that would return the wrong day when a datetimeoffset was inserted where the date
+ // was before 1/1/1970 and the time was midnight.
+ test( 'verify bug fix for dates older than 1/1/1970 with midnight time', function( test_done ) {
+ sql.open( conn_str, function( err, conn ) {
+
+ assert.ifError( err );
+
+ var midnightDate = new Date( Date.parse( "2030-08-13T00:00:00.000Z" ));
+
+ testBoilerPlate( 'midnight_date_test', { 'midnight_date_test': 'datetimeoffset(3)' },
+
+ function (done) {
+
+ var insertQuery = "INSERT INTO midnight_date_test (midnight_date_test) VALUES (?);";
+ conn.queryRaw( insertQuery, [ midnightDate ], function( e ) {
+
+ assert.ifError( e );
+ done();
+ });
+ },
+ // test valid dates
+ function( done ) {
+
+ conn.queryRaw( "SELECT midnight_date_test FROM midnight_date_test", function( e, r ) {
+
+ assert.ifError( e );
+
+ var expectedDates = [];
+ var expectedDate = midnightDate
+ expectedDates.push( [ expectedDate ]);
+ var expectedResults = { meta: [ { name: 'midnight_date_test', size: 30, nullable: true, type: 'date' } ],
+ rows: expectedDates
+ };
+ assert.deepEqual( expectedResults.meta, r.meta );
+ assert( r.rows.length == 1 );
+ for( var row in r.rows ) {
+ for( var d in row ) {
+ assert.deepEqual( expectedResults.rows[row][d], r.rows[row][d] );
+ }
+ }
+ done();
+ })
+ },
+ test_done );
+ });
+ });
+
+ // verify fix for a bug that would return the wrong day when a datetimeoffset was inserted where the date
+ // was before 1/1/1970 and the time was midnight.
+ test( 'verify bug fix for dates older than 1/1/1970 with midnight time', function( test_done ) {
+ sql.open( conn_str, function( err, conn ) {
+
+ assert.ifError( err );
+
+ var midnightDate = new Date( Date.parse( "1930-08-13T00:00:00.000Z" ));
+
+ testBoilerPlate( 'midnight_date_test', { 'midnight_date_test': 'datetimeoffset(3)' },
+
+ function (done) {
+
+ var insertQuery = "INSERT INTO midnight_date_test (midnight_date_test) VALUES (?);";
+ conn.queryRaw( insertQuery, [ midnightDate ], function( e ) {
+
+ assert.ifError( e );
+ done();
+ });
+ },
+ // test valid dates
+ function( done ) {
+
+ conn.queryRaw( "SELECT midnight_date_test FROM midnight_date_test", function( e, r ) {
+
+ assert.ifError( e );
+
+ var expectedDates = [];
+ var expectedDate = midnightDate
+ expectedDates.push( [ expectedDate ]);
+ var expectedResults = { meta: [ { name: 'midnight_date_test', size: 30, nullable: true, type: 'date' } ],
+ rows: expectedDates
+ };
+ assert.deepEqual( expectedResults.meta, r.meta );
+ assert( r.rows.length == 1 );
+ for( var row in r.rows ) {
+ for( var d in row ) {
+ assert.deepEqual( expectedResults.rows[row][d], r.rows[row][d] );
+ }
+ }
+ done();
+ })
+ },
+ test_done );
+ });
+ });
});

0 comments on commit f7d228f

Please sign in to comment.