strptime会始终用0填充缺失的值吗?

huangapple go评论57阅读模式
英文:

Can I assume that strptime will always fill in missing values with 0?

问题

以下是Perl代码的翻译部分:

print Time::Piece->strptime("2023:01:01 00:00:00.000", "%Y:%m:%d %H:%M:%S")->strftime("%Y:%m:%d %H:%M:%S") . "\n";
print Time::Piece->strptime("2023:01:02 00:00:00", "%Y:%m:%d %H:%M:%S%z")->strftime("%Y:%m:%d %H:%M:%S") . "\n";
print Time::Piece->strptime("2023:01:03 00:00", "%Y:%m:%d %H:%M:%S")->strftime("%Y:%m:%d %H:%M:%S") . "\n";

以下是输出部分的翻译:

第一个调用中strptime函数抱怨了输入字符串的问题然而在第二个和第三个调用中strptime函数没有抱怨输入字符串缺少的值它只是假设第二个调用的时区偏移%z+0000第三个调用的秒数%S为00

根据Time::Piece模块的文档strptime()函数来自FreeBSD我查看了FreeBSD的man页面关于strptime的说明没有提到输入字符串中缺少值的行为应该是什么样的

我正在Windows上运行ActivePerl但我可以假设在不同的操作系统或不同的Perl版本例如Strawberry Perl上会看到相同的行为吗

请注意,以上是代码和输出的翻译部分,不包括问题或额外信息。如果您需要更多翻译,请提出具体要求。

英文:

I have the following Perl code:

print Time::Piece->strptime("2023:01:01 00:00:00.000", "%Y:%m:%d %H:%M:%S")->strftime("%Y:%m:%d %H:%M:%S") . "\n";
print Time::Piece->strptime("2023:01:02 00:00:00", "%Y:%m:%d %H:%M:%S%z")->strftime("%Y:%m:%d %H:%M:%S") . "\n";
print Time::Piece->strptime("2023:01:03 00:00", "%Y:%m:%d %H:%M:%S")->strftime("%Y:%m:%d %H:%M:%S") . "\n";

It has the following output:

Garbage at end of string in strptime: .000 at C:/Perl64/lib/Time/Piece.pm line 581.
Perhaps a format flag did not match the actual input? at C:/Perl64/lib/Time/Piece.pm line 581.
2023:01:01 00:00:00
2023:01:02 00:00:00
2023:01:03 00:00:00

As you can see, in the first call strptime complained about the input string. However, in the second and third calls, strptime did not complain about the fact that the input string had missing values. It just assumed that the time zone offset (%z) for the second call was +0000, and that the seconds (%S) for the third call was 00.

According to the Time::Piece module documentation, the strptime() function comes from FreeBSD. I looked at the FreeBSD man page for strptime, and there is no mention of what the behavior should be with missing values in the input string.

I am running ActivePerl on Windows, but can I assume that I would see the same behavior (no complaints and assuming 0 for any missing values) on a different OS or a different flavor of Perl (e.g. Strawberry Perl)?

答案1

得分: 3

Time::Piece的strptime实现在处理不完整的字符串时,会根据第一个缺少数据的转换而有两种不同的行为。

对于某些情况,会返回错误(NULL)。当这种情况发生时,Time::Piece会抛出异常,但这与你的问题无关。

对于感兴趣的情况,解析会以未提供的timeptr成员保持不变,就好像它们在格式中没有提供一样。

因此,我们需要查看Time::Piece如何为默认值调用此函数。这是它如何初始化结构的方式:

memset(&mytm, 0, sizeof(mytm));
 
/* 合理的默认值 */
mytm.tm_mday = 1;
mytm.tm_year = 70;
mytm.tm_wday = 4;
mytm.tm_isdst = -1; /* -1 表示我们不知道 */

是的,小时、分钟和秒的值默认为零。

请记住,对于默认为零的转换,最终结果可能不为零,因为可能会指定一个不存在的日期时间。在这种情况下,Linux 会将时间四舍五入到最近的有效时间。

$ alias t='
   TZ=America/Sao_Paulo perl -e''
      use v5.14;
      use Time::Piece qw( localtime );
      say localtime->strptime( $ARGV[0], "%F %T" )->strftime( "%F %T" );
   ''
'

$ t '2013-10-20 02:00:00'
2013-10-20 02:00:00

$ t '2013-10-20 01:00:00'
2013-10-20 01:00:00

$ t '2013-10-20 00:00:00'  # 不存在
2013-10-20 01:00:00

$ t '2013-10-20'
2013-10-20 01:00:00
英文:

Looking at Time::Piece's implementation of the underlying strptime, one of two things happens when it comes to incomplete string, depending on the first conversion that lacked data.

For some, an error (NULL) is returned. Time::Piece croaks when this happens. It's not relevant to this question.

For those of interest, parsing ends with the unprovided members of timeptr left untouched, as if they weren't provided in the format.

So we need to look at how Time::Piece calls this function for the defaults. This is how it initializes the structure:

memset(&mytm, 0, sizeof(mytm));
 
/* sensible defaults. */
mytm.tm_mday = 1;
mytm.tm_year = 70;
mytm.tm_wday = 4;
mytm.tm_isdst = -1; /* -1 means we don't know */

So yes, the hour, minute and second values default to zero.

Keep in mind the the final result might not be zero for conversions that default to zero because it's possible to specify a date-time that doesn't exist. In such circumstances, Linux rounds up to the nearest valid time.

$ alias t='
   TZ=America/Sao_Paulo perl -e'\''
      use v5.14;
      use Time::Piece qw( localtime );
      say localtime->strptime( $ARGV[0], "%F %T" )->strftime( "%F %T" );
   '\''
'

$ t '2013-10-20 02:00:00'
2013-10-20 02:00:00

$ t '2013-10-20 01:00:00'
2013-10-20 01:00:00

$ t '2013-10-20 00:00:00'  # Doesn't exist
2013-10-20 01:00:00

$ t '2013-10-20'
2013-10-20 01:00:00

huangapple
  • 本文由 发表于 2023年5月10日 23:21:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220172.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定