/*
Copyright ( c ) 2023 , MariaDB
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 ; version 2 of the License .
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 , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1335 USA
*/
/*
This file tests my_tzset / my_get_tzinfo APIs
*/
#include <my_global.h>
#include <my_sys.h>
#include "tap.h"
#include <stdlib.h>
/**
Seconds since epoch used for " summer " timestamp
Corresponds to Jul 22 2023 04 : 26 : 40 GMT
Used to test timezone daylight savings UTC offset and DST abbreviation
*/
#define SUMMER_TIMESTAMP 1690000000
/**
Seconds since epoch used for " winter " timestamp
Corresponds to Nov 14 2023 22 : 13 : 20 GMT +
Used to test standard ( no daylight savings ) UTC offset and abbreviation
*/
#define WINTER_TIMESTAMP 1700000000
#ifdef _WIN32
#define timegm _mkgmtime
#endif
/**
Check expected offset from UTC , corresponding to specific
timestamp .
On Windows , it is possible that my_get_tzinfo ( ) is using
ICU to calculate offset . This function rechecks that value is the
same when using C runtime ' s _ mkgmtime ( ) .
Elsewhere , my_get_tzinfo is taking this value from non - standard glibc
extension struct tm : : tm_gmtoff . This function rechecks that the value
is the same if calculated with timegm ( ) .
*/
static void check_utc_offset(time_t t, long expected, const char *comment)
{
#if defined _WIN32 || defined __linux__
struct tm local_time;
long offset;
localtime_r(&t, &local_time);
offset= (long ) (timegm(&local_time) - t);
ok(offset == expected, "%s: Offset for timestamp %lld is %ld/%ld" , comment,
(long long ) t,expected, offset);
#else
skip(1 , "no utc offset check" );
#endif
}
/**
Test my_tzset / my_get_tzinfo functions for a single named timezone .
@ param [ in ] tz_env . Timezone name , as used for TZ env . variable
@ param [ in ] expected_tznames . Expected " sytem_timezone " names .
For example , expected names for timezone PST8PDT can
be PST8PDT , PST or PDT
@ param [ in ] summer_gmt_off . Expected UTC offset , for SUMMER_TIMESTAMP
For timezones with DST savings on northern hemisphere
it is the expected DST offset from UTC
@ param [ in ] summer_time_abbr . Expected standard abbreviation
corresponding to SUMMER_TIMESTAMP . For example , it is
" PDT " for timezone PST8PDT
@ param [ in ] winter_gmt_off . Expected UTC offset , for WINTER_TIMESTAMP
@ param [ in ] winter_time_abbr . Expected standard abbreviation
corresponding to WINTER_TIMESTAMP . For example , it is
" PST " for timezone PST8PDT .
*/
void test_timezone(const char *tz_env, const char **expected_tznames,
long summer_gmt_off, const char *summer_time_abbr,
long winter_gmt_off, const char *winter_time_abbr)
{
char timezone_name[64 ];
int found;
struct my_tz tz;
setenv("TZ" , tz_env, 1 );
my_tzset();
my_tzname(timezone_name, sizeof (timezone_name));
/* Check expected timezone names. */
found= 0 ;
for (int i= 0 ; expected_tznames[i]; i++)
{
if (!strcmp(expected_tznames[i], timezone_name))
{
found= 1 ;
break ;
}
}
ok(found, "%s: timezone_name = %s" , tz_env, timezone_name);
#if defined __linux__ && !defined __GLIBC__ && !defined __UCLIBC__
/*
MUSL incorrectly calculates UTC offsets and abbreviations
for certain values of TZ ( DST related ) . See MDEV - 38029
Skip tests in this case .
*/
if (!strcmp(tz_env, "PST8PDT" ) || !strcmp(tz_env, "GST-1GDT" ))
{
skip(6 , "musl UTC offset/abbreviation bug, tzname %s, see MDEV-38029" , tz_env);
return ;
}
#endif
my_tzinfo(SUMMER_TIMESTAMP, &tz);
ok(summer_gmt_off == tz.seconds_offset, "%s: Summer GMT offset %ld" , tz_env, tz.seconds_offset);
check_utc_offset(SUMMER_TIMESTAMP,tz.seconds_offset, tz_env);
ok(!strcmp(summer_time_abbr, tz.abbreviation), "%s: Summer time abbreviation %s" ,
tz_env, tz.abbreviation);
my_tzinfo(WINTER_TIMESTAMP, &tz);
ok(winter_gmt_off == tz.seconds_offset, "%s: Winter GMT offset %ld" , tz_env, tz.seconds_offset);
check_utc_offset(WINTER_TIMESTAMP, tz.seconds_offset, tz_env);
ok(!strcmp(winter_time_abbr, tz.abbreviation), "%s: Winter time abbreviation %s" ,
tz_env, tz.abbreviation);
}
/* Check default timezone.*/
static void test_default_timezone()
{
char timezone_name[64 ];
time_t timestamps[]= {SUMMER_TIMESTAMP, WINTER_TIMESTAMP, time(NULL)};
size_t i;
struct my_tz tz;
#ifdef _WIN32
(void ) putenv("TZ=" );
#else
unsetenv("TZ" );
#endif
my_tzset();
my_tzname(timezone_name, sizeof (timezone_name));
#ifdef _WIN32
/* Expect timezone name like Europe/Berlin */
ok(strstr(timezone_name, "/" ) != NULL, "Default timezone name %s" ,
timezone_name);
#else
skip(1 , "no test for default timezone name %s" , timezone_name);
#endif
for (i = 0 ; i < array_elements(timestamps); i++)
{
my_tzinfo(timestamps[i], &tz);
ok(tz.seconds_offset % 60 == 0 ,
"GMT offset is whole number of minutes %ld" , tz.seconds_offset);
check_utc_offset(timestamps[i], tz.seconds_offset, timezone_name);
ok(strlen(tz.abbreviation) < 8 , "tz abbreviation %s" , tz.abbreviation);
}
}
int main(int argc __attribute__((unused)), char *argv[])
{
const char *PST8PDT_names[]= {"PST" , "PDT" , "PST8PDT" , NULL};
const char *GMT_names[]= {"GMT" , "Etc/UTC" , NULL};
const char *GST_minus1GDT_names[]= {"GST" , "GDT" , NULL};
const char *IST_names[]= {"IST" ,NULL};
MY_INIT(argv[0 ]);
plan(38 );
test_default_timezone();
/*
Test PST8PDT timezone
Standard timezone , supported everywhere . Note - this one is supported by
ICU , so it would be using ICU for calculation on Windows
*/
test_timezone("PST8PDT" , PST8PDT_names, -25200 , "PDT" , -28800 , "PST" );
/*
Test GMT . Supported by ICU , would be using ICU for calculations
*/
test_timezone("GMT" , GMT_names, 0 , "GMT" , 0 , "GMT" );
/*
Non - standard " Germany " timezone , taken from Windows tzset ( ) documentation
example . Unsupported by ICU , will be using C runtime on Windows for
abbreviations , and offset calculations .
*/
test_timezone("GST-1GDT" , GST_minus1GDT_names, 7200 , "GDT" , 3600 , "GST" );
/* India */
test_timezone("IST-5:30" , IST_names, 19800 , "IST" , 19800 , "IST" );
my_end(0 );
return exit_status();
}
Messung V0.5 in Prozent C=94 H=93 G=93
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland