2015-03-26 19:59:06 -05:00
/********************************************************************\
* test - gnc - datetime . cpp - - Unit tests for GncDate and GncDateTime *
* *
* Copyright 2015 John Ralls < jralls @ ceridwen . us > *
* *
* This program is free software ; you can redistribute it and / or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation ; either version 2 of *
* the License , or ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , contact : *
* *
* Free Software Foundation Voice : + 1 - 617 - 542 - 5942 *
* 51 Franklin Street , Fifth Floor Fax : + 1 - 617 - 542 - 2652 *
* Boston , MA 02110 - 1301 , USA gnu @ gnu . org *
* *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "../gnc-datetime.hpp"
2023-06-01 10:10:36 -05:00
# include "../gnc-date.h"
2015-03-26 19:59:06 -05:00
# include <gtest/gtest.h>
2018-11-02 12:29:52 -05:00
/* Backdoor to enable unittests to temporarily override the timezone: */
2018-11-02 15:44:09 -05:00
class TimeZoneProvider ;
2018-11-02 12:29:52 -05:00
void _set_tzp ( TimeZoneProvider & tz ) ;
void _reset_tzp ( ) ;
2015-03-26 19:59:06 -05:00
TEST ( gnc_date_constructors , test_default_constructor )
{
GncDate date ;
EXPECT_FALSE ( date . isnull ( ) ) ;
}
TEST ( gnc_date_constructors , test_ymd_constructor )
{
GncDate date ( 2045 , 11 , 13 ) ;
EXPECT_FALSE ( date . isnull ( ) ) ;
}
2017-05-02 16:09:23 -05:00
TEST ( gnc_date_constructors , test_copy_constructor )
{
GncDate a ( 2045 , 11 , 13 ) ;
GncDate b ( a ) ;
EXPECT_FALSE ( a . isnull ( ) ) ;
EXPECT_TRUE ( a = = b ) ;
}
TEST ( gnc_date_constructors , test_move_constructor )
{
GncDate a ( 2045 , 11 , 13 ) ;
GncDate b ( std : : move ( a ) ) ;
EXPECT_TRUE ( a . isnull ( ) ) ;
EXPECT_TRUE ( b . format ( " %Y-%m-%d " ) = = " 2045-11-13 " ) ;
}
2017-04-21 09:58:20 -05:00
typedef struct
{
const char * date_fmt ;
const char * date_str ;
int exp_year ;
int exp_month ;
int exp_day ;
} parse_date_data ;
TEST ( gnc_date_constructors , test_str_format_constructor )
{
auto today = GncDate ( ) ;
auto today_ymd = today . year_month_day ( ) ;
auto curr_year = today_ymd . year ;
parse_date_data test_dates [ ] =
{
// supported combinations -/.'
{ " y-m-d " , " 2013-08-01 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 2013-8-01 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 2013-08-1 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 2013-8-1 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 13-08-01 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 13-8-01 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 13-08-1 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 13-8-1 " , 2013 , 8 , 1 } ,
{ " y-m-d " , " 2009/11/04 " , 2009 , 11 , 4 } ,
{ " y-m-d " , " 1985.3.12 " , 1985 , 3 , 12 } ,
{ " y-m-d " , " 3'6'8 " , 2003 , 6 , 8 } ,
{ " y-m-d " , " 20130801 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 01-08-2013 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 01-8-2013 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 1-08-2013 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 1-8-2013 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 01-08-13 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 01-8-13 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 1-08-13 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 1-8-13 " , 2013 , 8 , 1 } ,
{ " d-m-y " , " 04/11/2009 " , 2009 , 11 , 4 } ,
{ " d-m-y " , " 12.3.1985 " , 1985 , 3 , 12 } ,
{ " d-m-y " , " 8'6'3 " , 2003 , 6 , 8 } ,
{ " d-m-y " , " 01082013 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 08-01-2013 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 8-01-2013 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 08-1-2013 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 8-1-2013 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 08-01-13 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 8-01-13 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 08-1-13 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 8-1-13 " , 2013 , 8 , 1 } ,
{ " m-d-y " , " 11/04/2009 " , 2009 , 11 , 4 } ,
{ " m-d-y " , " 3.12.1985 " , 1985 , 3 , 12 } ,
{ " m-d-y " , " 6'8'3 " , 2003 , 6 , 8 } ,
{ " m-d-y " , " 08012013 " , 2013 , 8 , 1 } ,
{ " d-m " , " 01-08 " , curr_year , 8 , 1 } ,
{ " d-m " , " 01-8 " , curr_year , 8 , 1 } ,
{ " d-m " , " 1-08 " , curr_year , 8 , 1 } ,
{ " d-m " , " 1-8 " , curr_year , 8 , 1 } ,
{ " d-m " , " 04/11 " , curr_year , 11 , 4 } ,
{ " d-m " , " 12.3 " , curr_year , 3 , 12 } ,
{ " d-m " , " 8'6 " , curr_year , 6 , 8 } ,
{ " d-m " , " 0108 " , curr_year , 8 , 1 } ,
{ " m-d " , " 08-01 " , curr_year , 8 , 1 } ,
{ " m-d " , " 8-01 " , curr_year , 8 , 1 } ,
{ " m-d " , " 08-1 " , curr_year , 8 , 1 } ,
{ " m-d " , " 8-1 " , curr_year , 8 , 1 } ,
{ " m-d " , " 11/04 " , curr_year , 11 , 4 } ,
{ " m-d " , " 3.12 " , curr_year , 3 , 12 } ,
{ " m-d " , " 6'8 " , curr_year , 6 , 8 } ,
{ " m-d " , " 0801 " , curr_year , 8 , 1 } ,
// ambiguous date formats
// current parser doesn't know how to disambiguate
// and hence refuses to parse
// can possibly improved with a smarter parser
{ " y-m-d " , " 130801 " , - 1 , - 1 , - 1 } ,
{ " d-m-y " , " 010813 " , - 1 , - 1 , - 1 } ,
{ " m-d-y " , " 080113 " , - 1 , - 1 , - 1 } ,
// Combinations that don't make sense
// but can still be entered by a user
// Should ideally all result in refusal to parse...
{ " y-m-d " , " 08-01 " , - 1 , - 1 , - 1 } ,
{ " y-m-d " , " 0801 " , - 1 , - 1 , - 1 } ,
{ " d-m-y " , " 01-08 " , - 1 , - 1 , - 1 } ,
{ " d-m-y " , " 0108 " , - 1 , - 1 , - 1 } ,
{ " m-d-y " , " 08-01 " , - 1 , - 1 , - 1 } ,
{ " m-d-y " , " 0801 " , - 1 , - 1 , - 1 } ,
{ " d-m " , " 01-08-2013 " , - 1 , - 1 , - 1 } ,
{ " d-m " , " 01-08-13 " , - 1 , - 1 , - 1 } ,
{ " d-m " , " 08-08-08 " , - 1 , - 1 , - 1 } ,
{ " d-m " , " 01082013 " , - 1 , - 1 , - 1 } ,
{ " d-m " , " 010813 " , - 1 , - 1 , - 1 } ,
{ " d-m " , " 20130108 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 08-01-2013 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 08-01-13 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 2013-08-01 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 09-08-01 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 08012013 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 080113 " , - 1 , - 1 , - 1 } ,
{ " m-d " , " 20130801 " , - 1 , - 1 , - 1 } ,
// Unknown date format specifier should also trigger an exception
{ " y-d-m H:M:S " , " 20130801 " , - 1 , - 1 , - 1 } ,
// Sentinel to mark the end of available tests
{ " y-m-d " , NULL , 0 , 0 , 0 } ,
} ;
int i = 0 ;
while ( test_dates [ i ] . date_str )
{
int got_year = 0 , got_month = 0 , got_day = 0 ;
try
{
auto test_date = GncDate ( std : : string ( test_dates [ i ] . date_str ) , test_dates [ i ] . date_fmt ) ;
auto test_ymd = test_date . year_month_day ( ) ;
got_year = test_ymd . year ;
got_month = test_ymd . month ;
got_day = test_ymd . day ;
}
catch ( const std : : invalid_argument & e )
{
got_year = got_month = got_day = - 1 ;
}
EXPECT_TRUE ( ( got_year = = test_dates [ i ] . exp_year ) & &
( got_month = = test_dates [ i ] . exp_month ) & &
( got_day = = test_dates [ i ] . exp_day ) )
< < " GncDate constructor failed for str " < < test_dates [ i ] . date_str
< < " and fmt " < < test_dates [ i ] . date_fmt < < " . \n "
< < " Expected: year " < < test_dates [ i ] . exp_year
< < " , month " < < test_dates [ i ] . exp_month
< < " , day " < < test_dates [ i ] . exp_day < < " \n "
< < " Actual: year " < < got_year < < " , month "
< < got_month < < " , day " < < got_day < < " \n " ;
i + + ;
}
}
2017-04-29 11:01:12 -05:00
TEST ( gnc_date_operators , test_equality )
{
GncDate a ( 2017 , 1 , 6 ) ;
GncDate b ( 2017 , 1 , 6 ) ;
GncDate c ( 2015 , 6 , 13 ) ;
EXPECT_TRUE ( a = = b ) ;
EXPECT_FALSE ( a = = c ) ;
EXPECT_TRUE ( a ! = c ) ;
EXPECT_FALSE ( a ! = b ) ;
}
TEST ( gnc_date_operators , test_more_less_than )
{
GncDate a ( 2017 , 1 , 6 ) ;
GncDate b ( 2017 , 1 , 6 ) ;
GncDate c ( 2015 , 6 , 13 ) ;
EXPECT_TRUE ( a > = b ) ;
EXPECT_TRUE ( a < = b ) ;
EXPECT_FALSE ( a > b ) ;
EXPECT_FALSE ( a < b ) ;
EXPECT_TRUE ( a > c ) ;
EXPECT_TRUE ( a > = c ) ;
EXPECT_FALSE ( a < c ) ;
EXPECT_FALSE ( a < = c ) ;
EXPECT_TRUE ( c < a ) ;
EXPECT_TRUE ( c < = a ) ;
EXPECT_FALSE ( c > a ) ;
EXPECT_FALSE ( c > = a ) ;
}
2017-05-02 16:09:23 -05:00
TEST ( gnc_date_operators , test_copy_assignment )
{
GncDate a ( 2017 , 1 , 6 ) ;
GncDate b ;
b = a ;
EXPECT_TRUE ( a = = b ) ;
}
TEST ( gnc_date_operators , test_move_assignment )
{
GncDate a ( 2045 , 11 , 13 ) ;
GncDate b ;
b = std : : move ( a ) ;
EXPECT_TRUE ( a . isnull ( ) ) ;
EXPECT_TRUE ( b . format ( " %Y-%m-%d " ) = = " 2045-11-13 " ) ;
}
2015-03-26 19:59:06 -05:00
TEST ( gnc_datetime_constructors , test_default_constructor )
{
GncDateTime atime ;
2023-06-01 10:10:36 -05:00
time64 time_now = gnc_time ( nullptr ) ;
2017-01-14 13:49:48 -06:00
EXPECT_EQ ( static_cast < time64 > ( atime ) , static_cast < time64 > ( time_now ) ) ;
2015-03-26 19:59:06 -05:00
}
TEST ( gnc_datetime_constructors , test_time64_constructor )
{
const time64 time = 2394187200 ; //2045-11-13 12:00:00 Z
GncDateTime atime ( time ) ;
2015-04-10 11:33:51 -05:00
EXPECT_EQ ( static_cast < time64 > ( atime ) , time ) ;
2015-03-26 19:59:06 -05:00
}
2015-04-10 11:33:51 -05:00
2017-08-16 04:49:53 -05:00
TEST ( gnc_datetime_constructors , test_string_constructor )
{
2018-01-09 15:58:25 -06:00
/* Plain UTC date-time */
std : : string timestr ( " 2015-12-05 11:57:03 " ) ;
GncDateTime time1 ( timestr ) ;
auto tm = time1 . utc_tm ( ) ;
2017-08-16 04:49:53 -05:00
EXPECT_EQ ( tm . tm_year , 115 ) ;
EXPECT_EQ ( tm . tm_mon , 11 ) ;
EXPECT_EQ ( tm . tm_mday , 5 ) ;
2018-01-09 15:58:25 -06:00
EXPECT_EQ ( tm . tm_hour , 11 ) ;
EXPECT_EQ ( tm . tm_min , 57 ) ;
EXPECT_EQ ( tm . tm_sec , 3 ) ;
/* Datetime with an offset */
timestr = " 1993-07-22 15:21:19 +0300 " ;
GncDateTime time2 ( timestr ) ;
tm = time2 . utc_tm ( ) ;
EXPECT_EQ ( tm . tm_year , 93 ) ;
EXPECT_EQ ( tm . tm_mon , 6 ) ;
EXPECT_EQ ( tm . tm_mday , 22 ) ;
EXPECT_EQ ( tm . tm_hour , 12 ) ;
EXPECT_EQ ( tm . tm_min , 21 ) ;
EXPECT_EQ ( tm . tm_sec , 19 ) ;
/* Bug 767824 date-time */
timestr = " 1993-07-22 15:21:19 +0013 " ;
GncDateTime time3 ( timestr ) ;
tm = time3 . utc_tm ( ) ;
EXPECT_EQ ( tm . tm_year , 93 ) ;
EXPECT_EQ ( tm . tm_mon , 6 ) ;
EXPECT_EQ ( tm . tm_mday , 22 ) ;
EXPECT_EQ ( tm . tm_hour , 15 ) ;
EXPECT_EQ ( tm . tm_min , 8 ) ;
EXPECT_EQ ( tm . tm_sec , 19 ) ;
2018-01-09 16:58:43 -06:00
/* Squashed format from SQLite3 databases */
timestr = " 20151205115703 " ;
GncDateTime time4 ( timestr ) ;
tm = time4 . utc_tm ( ) ;
EXPECT_EQ ( tm . tm_year , 115 ) ;
EXPECT_EQ ( tm . tm_mon , 11 ) ;
EXPECT_EQ ( tm . tm_mday , 5 ) ;
EXPECT_EQ ( tm . tm_hour , 11 ) ;
EXPECT_EQ ( tm . tm_min , 57 ) ;
EXPECT_EQ ( tm . tm_sec , 3 ) ;
2017-08-16 04:49:53 -05:00
}
2015-04-26 18:44:39 -05:00
TEST ( gnc_datetime_constructors , test_struct_tm_constructor )
{
# ifdef HAVE_STRUCT_TM_GMTOFF
const struct tm tm { 0 , 0 , 12 , 13 , 10 , 145 , 0 , 0 , 0 , NULL , 0 } ;
# else
const struct tm tm { 0 , 0 , 12 , 13 , 10 , 145 , 0 , 0 , 0 } ;
# endif
const time64 time = 2394187200 ; //2045-11-13 12:00:00 Z
GncDateTime atime ( tm ) ;
2017-12-12 10:42:32 -06:00
EXPECT_EQ ( static_cast < time64 > ( atime ) + atime . offset ( ) , time ) ;
2015-04-26 18:44:39 -05:00
const struct tm tm1 = static_cast < struct tm > ( atime ) ;
EXPECT_EQ ( tm1 . tm_year , tm . tm_year ) ;
EXPECT_EQ ( tm1 . tm_mon , tm . tm_mon ) ;
2017-12-12 10:42:32 -06:00
// We have to contort these a bit to handle offsets > 12, e.g. New Zealand during DST.
// EXPECT_EQ(tm1.tm_mday - (11 + atime.offset() / 3600) / 24 , tm.tm_mday);
// EXPECT_EQ((24 + tm1.tm_hour - atime.offset() / 3600) % 24, tm.tm_hour);
2015-04-26 18:44:39 -05:00
EXPECT_EQ ( tm1 . tm_mday , tm . tm_mday ) ;
2017-12-12 10:42:32 -06:00
EXPECT_EQ ( tm1 . tm_hour , tm . tm_hour ) ;
2015-04-26 18:44:39 -05:00
EXPECT_EQ ( tm1 . tm_min , tm . tm_min ) ;
}
2015-04-26 20:01:23 -05:00
2017-04-20 15:58:35 -05:00
/* Note: the following tests for the constructor taking a GncDate as input parameter
* use GncDateTime ' s format ( ) member function to simplify the result checking .
* If there ' s a bug in this member function , these tests may fail in addition
* to the format test later in the test suite . Be sure to check that later
* test as well in case any of the below constructor tests fails . */
TEST ( gnc_datetime_constructors , test_gncdate_start_constructor )
{
2023-01-09 16:36:06 -06:00
const gnc_ymd aymd = { 2017 , 04 , 20 } ;
2017-04-20 15:58:35 -05:00
GncDateTime atime ( GncDate ( aymd . year , aymd . month , aymd . day ) , DayPart : : start ) ;
//Skipping timezone information as this can't be controlled.
EXPECT_EQ ( atime . format ( " %d-%m-%Y %H:%M:%S " ) , " 20-04-2017 00:00:00 " ) ;
}
2018-11-02 15:44:09 -05:00
/* Putting this here is a bit weird but it includes
* boost / date_time / local_time / local_time . hpp and that redefines struct
* tm in a way that breaks initializing the tm in
* test_struct_tm_constructor on Linux .
*/
# include "../gnc-timezone.hpp"
2018-11-02 12:29:52 -05:00
/* Summertime transitions have been a recurring problem. At the time of adding
* this test the GncDateEditor was refusing to set the date to 28 October 2018
* in the Europe / London timezone .
*/
TEST ( gnc_datetime_constructors , test_gncdate_BST_transition )
{
2023-01-09 16:36:06 -06:00
const gnc_ymd begins = { 2018 , 03 , 25 } ;
const gnc_ymd ends = { 2018 , 10 , 28 } ;
2019-02-08 13:40:21 -06:00
# ifdef __MINGW32__
TimeZoneProvider tzp { " GMT Standard Time " } ;
# else
2018-11-02 12:29:52 -05:00
TimeZoneProvider tzp ( " Europe/London " ) ;
2019-02-08 13:40:21 -06:00
# endif
2018-11-02 12:29:52 -05:00
_set_tzp ( tzp ) ;
GncDateTime btime ( GncDate ( begins . year , begins . month , begins . day ) , DayPart : : start ) ;
GncDateTime etime ( GncDate ( ends . year , ends . month , ends . day ) , DayPart : : start ) ;
_reset_tzp ( ) ;
EXPECT_EQ ( btime . format ( " %d-%m-%Y %H:%M:%S " ) , " 25-03-2018 00:00:00 " ) ;
EXPECT_EQ ( etime . format ( " %d-%m-%Y %H:%M:%S " ) , " 28-10-2018 00:00:00 " ) ;
}
2017-04-20 15:58:35 -05:00
TEST ( gnc_datetime_constructors , test_gncdate_end_constructor )
{
2023-01-09 16:36:06 -06:00
const gnc_ymd aymd = { 2046 , 11 , 06 } ;
2017-04-20 15:58:35 -05:00
GncDateTime atime ( GncDate ( aymd . year , aymd . month , aymd . day ) , DayPart : : end ) ;
//Skipping timezone information as this can't be controlled.
2017-04-28 09:38:30 -05:00
EXPECT_EQ ( atime . format ( " %d-%m-%Y %H:%M:%S " ) , " 06-11-2046 23:59:59 " ) ;
2017-04-20 15:58:35 -05:00
}
2020-11-06 18:54:22 -06:00
static : : testing : : AssertionResult
test_offset ( time64 start_time , int hour , int offset1 , int offset2 ,
const char * zone )
{
GncDateTime gdt { start_time + hour * 3600 } ;
if ( ( hour < 2 & & gdt . offset ( ) = = offset1 ) | |
( hour > = 2 & & gdt . offset ( ) = = offset2 ) )
return : : testing : : AssertionSuccess ( ) ;
else
return : : testing : : AssertionFailure ( ) < < zone < < " : " < < gdt . format ( " %D %T %z %q " ) < < " hour " < < hour ;
}
TEST ( gnc_datetime_constructors , test_DST_start_transition_time )
{
# ifdef __MINGW32__
TimeZoneProvider tzp_can { " A.U.S Eastern Standard Time " } ;
TimeZoneProvider tzp_la { " Pacific Standard Time " } ;
# else
TimeZoneProvider tzp_can ( " Australia/Canberra " ) ;
TimeZoneProvider tzp_la ( " America/Los_Angeles " ) ;
# endif
_set_tzp ( tzp_la ) ;
for ( auto hours = 0 ; hours < 23 ; + + hours )
EXPECT_TRUE ( test_offset ( 1583657940 , hours , - 28800 , - 25200 , " Los Angeles " ) ) ;
_reset_tzp ( ) ;
_set_tzp ( tzp_can ) ;
for ( auto hours = 0 ; hours < 23 ; + + hours )
EXPECT_TRUE ( test_offset ( 1601737140 , hours , 36000 , 39600 , " Canberra " ) ) ;
_reset_tzp ( ) ;
}
TEST ( gnc_datetime_constructors , test_DST_end_transition_time )
{
# ifdef __MINGW32__
TimeZoneProvider tzp_can { " A.U.S Eastern Standard Time " } ;
TimeZoneProvider tzp_la { " Pacific Standard Time " } ;
# else
TimeZoneProvider tzp_can ( " Australia/Canberra " ) ;
TimeZoneProvider tzp_la ( " America/Los_Angeles " ) ;
# endif
_set_tzp ( tzp_la ) ;
for ( auto hours = 0 ; hours < 23 ; + + hours )
EXPECT_TRUE ( test_offset ( 1604217540 , hours , - 25200 , - 28800 , " Los Angeles " ) ) ;
_reset_tzp ( ) ;
_set_tzp ( tzp_can ) ;
for ( auto hours = 0 ; hours < 23 ; + + hours )
EXPECT_TRUE ( test_offset ( 1586008740 , hours , 39600 , 36000 , " Canberra " ) ) ;
_reset_tzp ( ) ;
}
2021-03-20 17:49:54 -05:00
TEST ( gnc_datetime_constructors , test_create_in_transition )
{
# ifdef __MINGW32__
TimeZoneProvider tzp_br { " E. South America Standard Time " } ;
# else
TimeZoneProvider tzp_br ( " America/Sao_Paulo " ) ;
# endif
_set_tzp ( tzp_br ) ;
/* Test Daylight Savings start: When Sao Paolo had daylight
* savings time it ended at 23 : 59 : 59 and the next second was
* 01 : 00 : 00 so that ' s when the day starts .
*/
GncDate date0 { " 2018-11-03 " , " y-m-d " } ;
GncDateTime gncdt0 { date0 , DayPart : : end } ;
EXPECT_EQ ( gncdt0 . format_zulu ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-11-04 02:59:59 UTC " ) ;
EXPECT_EQ ( gncdt0 . format ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-11-03 23:59:59 -03 " ) ;
GncDate date1 { " 2018-11-04 " , " y-m-d " } ;
GncDateTime gncdt1 { date1 , DayPart : : start } ;
EXPECT_EQ ( gncdt1 . format_zulu ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-11-04 03:00:00 UTC " ) ;
EXPECT_EQ ( gncdt1 . format ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-11-04 01:00:00 -02 " ) ;
/* End of day, end of DST. We want one second before midnight in
2021-03-22 16:18:24 -05:00
* std time , i . e . - 03. Unfortunately sometimes boost : : date_time
* decides that it ' s still DST and returns the first one .
2021-03-20 17:49:54 -05:00
*/
GncDate date2 { " 2018-02-17 " , " y-m-d " } ;
GncDateTime gncdt2 { date2 , DayPart : : end } ;
2021-03-22 16:18:24 -05:00
if ( gncdt2 . offset ( ) = = - 7200 )
{
EXPECT_EQ ( gncdt2 . format_zulu ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-02-18 01:59:59 UTC " ) ;
EXPECT_EQ ( gncdt2 . format ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-02-17 23:59:59 -02 " ) ;
}
else
{
EXPECT_EQ ( gncdt2 . format_zulu ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-02-18 02:59:59 UTC " ) ;
EXPECT_EQ ( gncdt2 . format ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2018-02-17 23:59:59 -03 " ) ;
}
2021-03-20 17:49:54 -05:00
/* After February 2019 Sao Paulo discontinued Daylight
* Savings . This test checks to ensure that GncTimeZone doesn ' t
* try to project 2018 ' s rule forward .
*/
GncDate date3 { " 2019-11-01 " , " y-m-d " } ;
GncDateTime gncdt3 { date3 , DayPart : : start } ;
EXPECT_EQ ( gncdt3 . format_zulu ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2019-11-01 03:00:00 UTC " ) ;
EXPECT_EQ ( gncdt3 . format ( " %Y-%m-%d %H:%M:%S %Z " ) , " 2019-11-01 00:00:00 -03 " ) ;
}
2017-04-20 15:58:35 -05:00
TEST ( gnc_datetime_constructors , test_gncdate_neutral_constructor )
{
2021-03-20 17:49:54 -05:00
# ifdef __MINGW32__
TimeZoneProvider tzp_la { " Pacific Standard Time " } ;
# else
TimeZoneProvider tzp_la ( " America/Los_Angeles " ) ;
# endif
_set_tzp ( tzp_la ) ;
2023-01-09 16:36:06 -06:00
const gnc_ymd aymd = { 2017 , 04 , 20 } ;
2017-04-20 15:58:35 -05:00
GncDateTime atime ( GncDate ( aymd . year , aymd . month , aymd . day ) , DayPart : : neutral ) ;
2020-03-14 12:15:12 -05:00
time64 date { 1492685940 } ;
GncDateTime gncdt ( date ) ; /* 20 Apr 2017 10:59:00 Z */
2023-01-09 16:36:06 -06:00
/* The gnc_ymd constructor sets the time of day at 10:59:00 for
2017-12-15 12:13:41 -06:00
* timezones between UTC - 10 and UTC + 13. For other timezones the
* time of day is adjusted to ensure a consistent date and the
* adjustment invalidates the test , so skip it .
*/
constexpr time64 max_western_offset = - 10 * 3600 ;
constexpr time64 max_eastern_offset = 13 * 3600 ;
2017-12-27 08:32:54 -06:00
if ( gncdt . offset ( ) > = max_western_offset & &
gncdt . offset ( ) < = max_eastern_offset )
{
2021-03-20 17:49:54 -05:00
EXPECT_EQ ( atime . format_zulu ( " %d-%m-%Y %H:%M:%S %Z " ) ,
" 20-04-2017 10:59:00 UTC " ) ;
2020-03-14 12:15:12 -05:00
EXPECT_EQ ( date , static_cast < time64 > ( gncdt ) ) ;
EXPECT_EQ ( date , static_cast < time64 > ( atime ) ) ;
2017-12-27 08:32:54 -06:00
}
2017-04-20 15:58:35 -05:00
}
2020-03-14 12:15:12 -05:00
TEST ( gnc_datetime_constructors , test_neutral_across_timezones )
{
2023-01-09 16:36:06 -06:00
const gnc_ymd begins = { 2018 , 03 , 05 } ;
const gnc_ymd ends = { 2018 , 03 , 15 } ;
2020-03-14 12:15:12 -05:00
const time64 ten_days = 864000 ;
# ifdef __MINGW32__
TimeZoneProvider tzp_lon { " GMT Standard Time " } ;
TimeZoneProvider tzp_perth { " W. Australia Standard Time " } ;
TimeZoneProvider tzp_la { " Pacific Standard Time " } ;
# else
TimeZoneProvider tzp_lon ( " Europe/London " ) ;
TimeZoneProvider tzp_perth ( " Australia/Perth " ) ;
TimeZoneProvider tzp_la ( " America/Los_Angeles " ) ;
# endif
_set_tzp ( tzp_lon ) ;
GncDateTime btime_lon ( GncDate ( begins . year , begins . month , begins . day ) , DayPart : : neutral ) ;
GncDateTime etime_lon ( GncDate ( ends . year , ends . month , ends . day ) , DayPart : : neutral ) ;
_reset_tzp ( ) ;
_set_tzp ( tzp_perth ) ;
GncDateTime btime_perth ( GncDate ( begins . year , begins . month , begins . day ) , DayPart : : neutral ) ;
GncDateTime etime_perth ( GncDate ( ends . year , ends . month , ends . day ) , DayPart : : neutral ) ;
_reset_tzp ( ) ;
_set_tzp ( tzp_la ) ;
GncDateTime btime_la ( GncDate ( begins . year , begins . month , begins . day ) , DayPart : : neutral ) ;
GncDateTime etime_la ( GncDate ( ends . year , ends . month , ends . day ) , DayPart : : neutral ) ;
_reset_tzp ( ) ;
EXPECT_EQ ( static_cast < time64 > ( btime_lon ) , static_cast < time64 > ( btime_perth ) ) ;
EXPECT_EQ ( static_cast < time64 > ( btime_lon ) , static_cast < time64 > ( btime_la ) ) ;
EXPECT_EQ ( static_cast < time64 > ( etime_lon ) , static_cast < time64 > ( etime_perth ) ) ;
EXPECT_EQ ( static_cast < time64 > ( etime_lon ) , static_cast < time64 > ( etime_la ) ) ;
EXPECT_EQ ( ten_days , static_cast < time64 > ( etime_lon ) - static_cast < time64 > ( btime_lon ) ) ;
EXPECT_EQ ( ten_days , static_cast < time64 > ( etime_perth ) - static_cast < time64 > ( btime_perth ) ) ;
EXPECT_EQ ( ten_days , static_cast < time64 > ( etime_la ) - static_cast < time64 > ( btime_la ) ) ;
}
2015-04-26 20:01:23 -05:00
TEST ( gnc_datetime_functions , test_format )
{
GncDateTime atime ( 2394187200 ) ; //2045-11-13 12:00:00 Z
2017-12-19 16:34:10 -06:00
if ( ( atime . offset ( ) / 3600 ) > 11 )
2017-12-12 10:42:32 -06:00
EXPECT_EQ ( atime . format ( " %d-%m-%Y " ) , " 14-11-2045 " ) ;
else
EXPECT_EQ ( atime . format ( " %d-%m-%Y " ) , " 13-11-2045 " ) ;
2015-04-26 20:01:23 -05:00
}
2015-04-28 12:06:18 -05:00
2016-11-06 11:39:21 -06:00
TEST ( gnc_datetime_functions , test_format_zulu )
{
GncDateTime atime ( 2394187200 ) ; //2045-11-13 12:00:00 Z
//Date only to finesse timezone issues. It will still fail in +12 DST.
EXPECT_EQ ( atime . format_zulu ( " %d-%m-%Y %H:%M:%S " ) , " 13-11-2045 12:00:00 " ) ;
}
2015-04-30 14:23:25 -05:00
//This is a bit convoluted because it uses GncDate's GncDateImpl constructor and year_month_day() function. There's no good way to test the former without violating the privacy of the implementation.
2015-04-28 12:06:18 -05:00
TEST ( gnc_datetime_functions , test_date )
{
GncDateTime atime ( 2394187200 ) ; //2045-11-13 12:00:00 Z
2016-06-02 14:44:38 -05:00
GncDate gncd = atime . date ( ) ;
2015-04-30 14:23:25 -05:00
auto ymd = gncd . year_month_day ( ) ;
2015-04-28 12:06:18 -05:00
EXPECT_EQ ( ymd . year , 2045 ) ;
EXPECT_EQ ( ymd . month , 11 ) ;
2017-12-12 10:42:32 -06:00
EXPECT_EQ ( ymd . day - ( 12 + atime . offset ( ) / 3600 ) / 24 , 13 ) ;
2015-04-28 12:06:18 -05:00
}
2017-12-12 10:42:32 -06:00
/* This test works only in the America/LosAngeles time zone and
2021-03-16 00:34:08 -05:00
* there ' s no straightforward way to make it more flexible . It ensures
2021-03-15 19:04:39 -05:00
* that DST in that timezone transitions correctly for each day of the
Fix various typos
Found via `codespell -q 3 -S *.po,./po,*.min.js,./ChangeLog*,./NEWS,./borrowed,./doc/README*,./AUTHORS,./libgnucash/tax/us/txf-de*,./data/accounts -L ans,ba,cas,dragable,gae,iff,iif,mut,nd,numer,parm,parms,startd,stoll`
2022-04-01 08:02:10 -05:00
* week in which March begins .
2021-03-15 19:04:39 -05:00
TEST ( gnc_datetime_functions , test_timezone_offset )
2017-03-17 17:18:00 -05:00
{
2021-03-15 19:04:39 -05:00
struct Timepair
{
time64 before ;
time64 after ;
} ;
std : : array < Timepair , 7 > years {
Timepair { 1615633140 , 1615719540 } , //2021, Monday
Timepair { 1457780340 , 1457866740 } , //2016, Tuesday
Timepair { 1489229940 , 1489316340 } , //2017, Wednesday
Timepair { 1520679540 , 1520765940 } , //2018, Thursday
Timepair { 1552129140 , 1552215540 } , //2019, Friday
Timepair { 1741431540 , 1741517940 } , //2025, Saturday
Timepair { 1583578740 , 1583665140 } //2020, Sunday
} ;
for ( auto year : years )
{
GncDateTime before { year . before } ;
GncDateTime after { year . after } ;
// std::cerr << before.format_iso8601() << std::endl;
EXPECT_EQ ( - 28800 , before . offset ( ) ) ;
EXPECT_EQ ( - 25200 , after . offset ( ) ) ;
}
2017-03-17 17:18:00 -05:00
}
2017-12-12 10:42:32 -06:00
*/