SBECK-github / Date-Manip

Other
10 stars 11 forks source link

printf format '%F' doesn't follow strftime #48

Closed pattieja1 closed 7 months ago

pattieja1 commented 10 months ago

While updating my code to work around issues I encountered with the v6 functional interface and converting to using the OO interface, I switched from how I was using the following code path to calculate an offset and then format for output:

my $time = DataCalc($date, $offset);
$time = UnixDate($time, '%s');
@tm = localtime($time);
$result = strftime($format, @tm);

Latest perl and Date::Manip modules was causing this code to return the wrong date when trying to add 24 hours to a date and have it just spit out YYYY-MM-DD. I was using '%F' as strftime spits out the format in question.

Converting the above code to use your OO interface gives me the correct date now but '%F' isn't what I'm expecting so I have to spell out '%Y-%m-%d' as the format, which was a nasty surprise.

  my $dmObj = Date::Manip::Date->new();
  my $deltaObj = Date::Manip::Delta->new();
  my $err = $dmObj->parse($date);
  if ($err) {
    logger->error("getDateOffset(): failed to parse date='$date'.  err='$err'");
    return '';
  }
  $deltaObj->parse($offset);
  my $new_date = $dmObj->calc($deltaObj);
  my $result = $new_date->printf($format);  

I guess there's 2 issues here. Why does the above functional code no longer work? I'm assuming it's got something to do with your TZ changes. Where'd your version of '%F' come from? :)

pattieja1 commented 10 months ago

I'm using Date::Manip 6.92 on perl: Summary of my perl5 (revision 5 version 38 subversion 0) configuration:

Platform: osname=linux osvers=3.10.0-1160.el7.x86_64 archname=x86_64-linux-thread-multi uname='linux buildkitsandbox 3.10.0-1160.el7.x86_64 #1 smp mon oct 19 16:18:59 utc 2020 x86_64 gnulinux ' config_args='-des -Dprefix=/opt/gpsi/perl/local/perl -Dusethreads -Accflags=-DAPPLLIB_EXP=\"/opt/gpsi/perl/local/lib/perl5\" -A'eval:scriptdir=/opt/gpsi/perl/local/perl/bin'' hint=recommended useposix=true d_sigaction=define useithreads=define usemultiplicity=define use64bitint=define use64bitall=define uselongdouble=undef usemymalloc=n default_inc_excludes_dot=define Compiler: cc='cc' ccflags ='-D_REENTRANT -D_GNU_SOURCE -DAPPLLIB_EXP="/opt/gpsi/perl/local/lib/perl5" -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2' optimize='-O2' cppflags='-D_REENTRANT -D_GNU_SOURCE -DAPPLLIB_EXP="/opt/gpsi/perl/local/lib/perl5" -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include' ccversion='' gccversion='12.2.0' gccosandvers='' intsize=4 longsize=8 ptrsize=8 doublesize=8 byteorder=12345678 doublekind=3 d_longlong=define longlongsize=8 d_longdbl=define longdblsize=16 longdblkind=3 ivtype='long' ivsize=8 nvtype='double' nvsize=8 Off_t='off_t' lseeksize=8 alignbytes=8 prototype=define Linker and Libraries: ld='cc' ldflags =' -fstack-protector-strong -L/usr/local/lib' libpth=/usr/local/lib /usr/lib/x86_64-linux-gnu /usr/lib /usr/lib64 libs=-lpthread -ldl -lm -lcrypt -lutil -lc perllibs=-lpthread -ldl -lm -lcrypt -lutil -lc libc=/lib/x86_64-linux-gnu/libc.so.6 so=so useshrplib=false libperl=libperl.a gnulibc_version='2.36' Dynamic Linking: dlsrc=dl_dlopen.xs dlext=so d_dlsymun=undef ccdlflags='-Wl,-E' cccdlflags='-fPIC' lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'

Characteristics of this binary (from libperl): Compile-time options: HAS_LONG_DOUBLE HAS_STRTOLD HAS_TIMES MULTIPLICITY PERLIO_LAYERS PERL_COPY_ON_WRITE PERL_DONT_CREATE_GVSV PERL_HASH_FUNC_SIPHASH13 PERL_HASH_USE_SBOX32 PERL_MALLOC_WRAP PERL_OP_PARENT PERL_PRESERVE_IVUV PERL_USE_SAFE_PUTENV USE_64_BIT_ALL USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_LOCALE_TIME USE_PERLIO USE_PERL_ATOF USE_REENTRANT_API USE_THREAD_SAFE_LOCALE Built under linux Compiled at Aug 9 2023 23:09:51 @INC: /opt/gpsi/perl/local/lib/perl5/x86_64-linux-thread-multi /opt/gpsi/perl/local/lib/perl5 /opt/gpsi/perl/local/perl/lib/site_perl/5.38.0/x86_64-linux-thread-multi /opt/gpsi/perl/local/perl/lib/site_perl/5.38.0 /opt/gpsi/perl/local/perl/lib/5.38.0/x86_64-linux-thread-multi /opt/gpsi/perl/local/perl/lib/5.38.0

pattieja1 commented 10 months ago

I tracked down my issue with the original functional code not working anymore. In the docker environment I had /etc/localtime symlinked to America/Phoenix but the /etc/timezone was still saying 'Etc/UTC' instead of 'America/Phoenix'.

This code was working under Perl 5.26.3 and Date::Manip 6.75. Did Date::Manip switch to using /etc/timezone after that or was I just getting lucky? localtime was 7 hours off from what Date::Manip was working with.

SBECK-github commented 10 months ago

Sorry I haven't had time to look into this.

Date::Manip uses quite a few methods to determine the local timezone. They are documented here:

https://metacpan.org/pod/Date::Manip::TZ#DETERMINING-THE-SYSTEM-TIME-ZONE

And yes, one of them is to use /etc/timezone.

pattieja1 commented 10 months ago

I've got the code issue resolved after I had found that documentation last night and figured out what was going on.

Any chance of making your '%whatever' formatting strings match the core of what Posix::strftime uses for consistency?

%F is the biggest difference I've seen and was the default formatting string in my code. I've also used %u.

SBECK-github commented 10 months ago

So I just went through the strftime formatting strings, and agree that several differ (I tried to base mine on standards, but it appears they date back prior to the current POSIX strftime.

In any case, I can't just replace them as that could break existing code. I will look into making a new config variable that you can set to use these instead of the default ones.

pattieja1 commented 10 months ago

Thanks. Is there a way to currently replace what '%F' is doing, at runtime, or would that be touching the private internals and a no-no? :)

SBECK-github commented 10 months ago

There's no way to replace %F (short of going in and modifying the program). Mind you, you're welcome to do so (and I suspect it won't be hard), but that will make it hard to upgrade, so I'd probably just use the longer %Y-%m-%d format.

SBECK-github commented 7 months ago

I've completed the work to add most of the POSIX strftime formats. There is a new config variable (use_posix_printf) which will allow you to use most of the strftime directives. There's a few which are not yet supported. The next release (which comes out in a couple weeks) will have this.