1*6a7405f5SSimon J. Gerraty# $NetBSD: varmod-gmtime.mk,v 1.27 2025/01/11 20:54:45 rillig Exp $ 22c3632d1SSimon J. Gerraty# 32c3632d1SSimon J. Gerraty# Tests for the :gmtime variable modifier, which formats a timestamp 4956e45f6SSimon J. Gerraty# using strftime(3) in UTC. 5c1d01b5fSSimon J. Gerraty# 6c1d01b5fSSimon J. Gerraty# See also: 7c1d01b5fSSimon J. Gerraty# varmod-localtime.mk 82c3632d1SSimon J. Gerraty 906b9b3e0SSimon J. Gerraty.if ${TZ:Uundefined} != "undefined" # see unit-tests/Makefile 1006b9b3e0SSimon J. Gerraty. error 1106b9b3e0SSimon J. Gerraty.endif 12956e45f6SSimon J. Gerraty 13956e45f6SSimon J. Gerraty# Test for the default time format, %c. Since the time always varies, it's 14956e45f6SSimon J. Gerraty# only possible to check for the general format here. The names of the 15956e45f6SSimon J. Gerraty# month and weekday are always in English, independent from the locale. 16956e45f6SSimon J. Gerraty# Example: Thu Oct 29 18:56:41 2020 17956e45f6SSimon J. Gerraty.if ${:U:gmtime:tW:M??? ??? ?? ??\:??\:?? ????} == "" 18956e45f6SSimon J. Gerraty. error 19956e45f6SSimon J. Gerraty.endif 202c3632d1SSimon J. Gerraty 21956e45f6SSimon J. Gerraty 2206b9b3e0SSimon J. Gerraty# modifier name too short, falling back to the SysV modifier. 2306b9b3e0SSimon J. Gerraty.if ${%Y:L:gmtim=1593536400} != "%Y" 2406b9b3e0SSimon J. Gerraty. error 2506b9b3e0SSimon J. Gerraty.endif 2606b9b3e0SSimon J. Gerraty 27956e45f6SSimon J. Gerraty 28956e45f6SSimon J. Gerraty# 2020-07-01T00:00:00Z 2906b9b3e0SSimon J. Gerraty.if ${%Y:L:gmtime=1593536400} != "2020" 3006b9b3e0SSimon J. Gerraty. error 3106b9b3e0SSimon J. Gerraty.endif 32956e45f6SSimon J. Gerraty 3306b9b3e0SSimon J. Gerraty 3406b9b3e0SSimon J. Gerraty# modifier name too long, falling back to the SysV modifier. 3506b9b3e0SSimon J. Gerraty.if ${%Y:L:gmtimer=1593536400} != "%Y" 3606b9b3e0SSimon J. Gerraty. error 3706b9b3e0SSimon J. Gerraty.endif 3806b9b3e0SSimon J. Gerraty 39956e45f6SSimon J. Gerraty 40956e45f6SSimon J. Gerraty# If the modifier name is not matched exactly, fall back to the 41956e45f6SSimon J. Gerraty# :from=to modifier. 4206b9b3e0SSimon J. Gerraty.if ${gmtime:L:gm%=local%} != "localtime" 4306b9b3e0SSimon J. Gerraty. error 4406b9b3e0SSimon J. Gerraty.endif 452c3632d1SSimon J. Gerraty 462c3632d1SSimon J. Gerraty 47c1d01b5fSSimon J. Gerraty# Before var.c 1.1050 from 2023-05-09, it was not possible to pass the 48d5e0a182SSimon J. Gerraty# seconds via an expression. 49c1d01b5fSSimon J. Gerraty.if ${%Y:L:gmtime=${:U1593536400}} != "2020" 5006b9b3e0SSimon J. Gerraty. error 5106b9b3e0SSimon J. Gerraty.endif 522c3632d1SSimon J. Gerraty 53956e45f6SSimon J. Gerraty 5406b9b3e0SSimon J. Gerraty# Before var.c 1.631 from 2020-10-31 21:40:20, it was possible to pass 5506b9b3e0SSimon J. Gerraty# negative time stamps to the :gmtime modifier, resulting in dates before 5606b9b3e0SSimon J. Gerraty# 1970. Going back 50 years in the past is not a practical use case for 5706b9b3e0SSimon J. Gerraty# make. Therefore, since var.c 1.631, negative time stamps produce a 5806b9b3e0SSimon J. Gerraty# parse error. 59*6a7405f5SSimon J. Gerraty# expect+1: Invalid time value "-1" 6006b9b3e0SSimon J. Gerraty.if ${:L:gmtime=-1} != "" 6106b9b3e0SSimon J. Gerraty. error 6206b9b3e0SSimon J. Gerraty.else 6306b9b3e0SSimon J. Gerraty. error 6406b9b3e0SSimon J. Gerraty.endif 65956e45f6SSimon J. Gerraty 66956e45f6SSimon J. Gerraty 67dba7b0efSSimon J. Gerraty# Spaces were allowed before var.c 1.631 from 2020-10-31 21:40:20, not 68dba7b0efSSimon J. Gerraty# because it would make sense but just as a side-effect from using strtoul. 69*6a7405f5SSimon J. Gerraty# expect+1: Invalid time value " 1" 7006b9b3e0SSimon J. Gerraty.if ${:L:gmtime= 1} != "" 7106b9b3e0SSimon J. Gerraty. error 72c1d01b5fSSimon J. Gerraty.else 73c1d01b5fSSimon J. Gerraty. error 7406b9b3e0SSimon J. Gerraty.endif 75956e45f6SSimon J. Gerraty 76956e45f6SSimon J. Gerraty 7706b9b3e0SSimon J. Gerraty# 0 means now; this differs from GNode.mtime, where a 0 means nonexistent. 7806b9b3e0SSimon J. Gerraty# Since "now" constantly changes, the strongest possible test is to match the 7906b9b3e0SSimon J. Gerraty# resulting pattern. 8006b9b3e0SSimon J. Gerraty.if !${:L:gmtime=0:tW:M??? ??? ?? ??\:??\:?? 20??} 8106b9b3e0SSimon J. Gerraty. error 8206b9b3e0SSimon J. Gerraty.endif 83956e45f6SSimon J. Gerraty 84956e45f6SSimon J. Gerraty 8506b9b3e0SSimon J. Gerraty.if ${:L:gmtime=1} != "Thu Jan 1 00:00:01 1970" 8606b9b3e0SSimon J. Gerraty. error 8706b9b3e0SSimon J. Gerraty.endif 88956e45f6SSimon J. Gerraty 8906b9b3e0SSimon J. Gerraty 9006b9b3e0SSimon J. Gerraty# INT32_MAX 9106b9b3e0SSimon J. Gerraty.if ${:L:gmtime=2147483647} != "Tue Jan 19 03:14:07 2038" 9206b9b3e0SSimon J. Gerraty. error 9306b9b3e0SSimon J. Gerraty.endif 9406b9b3e0SSimon J. Gerraty 9506b9b3e0SSimon J. Gerraty 9606b9b3e0SSimon J. Gerraty.if ${:L:gmtime=2147483648} == "Tue Jan 19 03:14:08 2038" 9706b9b3e0SSimon J. Gerraty# All systems that have unsigned time_t or 64-bit time_t. 98dba7b0efSSimon J. Gerraty.elif ${:L:gmtime=2147483648} == "Fri Dec 13 20:45:52 1901" 99dba7b0efSSimon J. Gerraty# FreeBSD-12.0-i386 still has 32-bit signed time_t, see 100dba7b0efSSimon J. Gerraty# sys/x86/include/_types.h, __LP64__. 101dba7b0efSSimon J. Gerraty# 102dba7b0efSSimon J. Gerraty# Linux on 32-bit systems may still have 32-bit signed time_t, see 103dba7b0efSSimon J. Gerraty# sysdeps/unix/sysv/linux/generic/bits/typesizes.h, __TIMESIZE. 10406b9b3e0SSimon J. Gerraty.else 10506b9b3e0SSimon J. Gerraty. error 10606b9b3e0SSimon J. Gerraty.endif 10706b9b3e0SSimon J. Gerraty 10806b9b3e0SSimon J. Gerraty 10906b9b3e0SSimon J. Gerraty# Integer overflow, at least before var.c 1.631 from 2020-10-31. 11006b9b3e0SSimon J. Gerraty# Because this modifier is implemented using strtoul, the parsed time was 11106b9b3e0SSimon J. Gerraty# ULONG_MAX, which got converted to -1. This resulted in a time stamp of 11206b9b3e0SSimon J. Gerraty# the second before 1970. 11306b9b3e0SSimon J. Gerraty# 114c1d01b5fSSimon J. Gerraty# Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a 115c1d01b5fSSimon J. Gerraty# parse error. 116*6a7405f5SSimon J. Gerraty# expect+1: Invalid time value "10000000000000000000000000000000" 11706b9b3e0SSimon J. Gerraty.if ${:L:gmtime=10000000000000000000000000000000} != "" 11806b9b3e0SSimon J. Gerraty. error 11906b9b3e0SSimon J. Gerraty.else 12006b9b3e0SSimon J. Gerraty. error 12106b9b3e0SSimon J. Gerraty.endif 12206b9b3e0SSimon J. Gerraty 12306b9b3e0SSimon J. Gerraty# Before var.c 1.631 from 2020-10-31, there was no error handling while 124dba7b0efSSimon J. Gerraty# parsing the :gmtime modifier, thus no error message was printed. Parsing 12506b9b3e0SSimon J. Gerraty# stopped after the '=', and the remaining string was parsed for more variable 12606b9b3e0SSimon J. Gerraty# modifiers. Because of the unknown modifier 'e' from the 'error', the whole 12706b9b3e0SSimon J. Gerraty# variable value was discarded and thus not printed. 128*6a7405f5SSimon J. Gerraty# expect+1: Invalid time value "error" 12906b9b3e0SSimon J. Gerraty.if ${:L:gmtime=error} != "" 13006b9b3e0SSimon J. Gerraty. error 13106b9b3e0SSimon J. Gerraty.else 13206b9b3e0SSimon J. Gerraty. error 13306b9b3e0SSimon J. Gerraty.endif 13406b9b3e0SSimon J. Gerraty 135c1d01b5fSSimon J. Gerraty# Before var.c 1.1050 from 2023-05-09, the timestamp could be directly 136c1d01b5fSSimon J. Gerraty# followed by the next modifier, without a ':' separator. This was the same 137c1d01b5fSSimon J. Gerraty# bug as for the ':L' and ':P' modifiers. 138*6a7405f5SSimon J. Gerraty# expect+1: Invalid time value "100000S,1970,bad," 139c1d01b5fSSimon J. Gerraty.if ${%Y:L:gmtime=100000S,1970,bad,} != "bad" 140c1d01b5fSSimon J. Gerraty. error 141c1d01b5fSSimon J. Gerraty.endif 14206b9b3e0SSimon J. Gerraty 14398875883SSimon J. Gerraty 14498875883SSimon J. Gerraty# Before var.c 1.1062 from 2023-08-19, ':gmtime' but not ':localtime' reported 14598875883SSimon J. Gerraty# wrong values for '%s', depending on the operating system and the timezone. 14698875883SSimon J. Gerratyexport TZ=UTC 14798875883SSimon J. Gerraty.for t in ${%s:L:gmtime} ${%s:L:localtime} 14898875883SSimon J. GerratyTIMESTAMPS+= $t 14998875883SSimon J. Gerraty.endfor 15098875883SSimon J. Gerratyexport TZ=Europe/Berlin 15198875883SSimon J. Gerraty.for t in ${%s:L:gmtime} ${%s:L:localtime} 15298875883SSimon J. GerratyTIMESTAMPS+= $t 15398875883SSimon J. Gerraty.endfor 15498875883SSimon J. Gerratyexport TZ=UTC 15598875883SSimon J. Gerraty.for t in ${%s:L:gmtime} ${%s:L:localtime} 15698875883SSimon J. GerratyTIMESTAMPS+= $t 15798875883SSimon J. Gerraty.endfor 15898875883SSimon J. Gerratyexport TZ=America/Los_Angeles 15998875883SSimon J. Gerraty.for t in ${%s:L:gmtime} ${%s:L:localtime} 16098875883SSimon J. GerratyTIMESTAMPS+= $t 16198875883SSimon J. Gerraty.endfor 16298875883SSimon J. Gerratyexport TZ=UTC 16398875883SSimon J. Gerraty.for t in ${%s:L:gmtime} ${%s:L:localtime} 16498875883SSimon J. GerratyTIMESTAMPS+= $t 16598875883SSimon J. Gerraty.endfor 16698875883SSimon J. Gerraty.for a b in ${TIMESTAMPS:[1]} ${TIMESTAMPS:@t@$t $t@} ${TIMESTAMPS:[-1]} 16798875883SSimon J. Gerraty. if $a > $b 16898875883SSimon J. Gerraty. warning timestamp $a > $b 16998875883SSimon J. Gerraty. endif 17098875883SSimon J. Gerraty.endfor 17198875883SSimon J. Gerraty 172d5e0a182SSimon J. Gerraty 173d5e0a182SSimon J. Gerraty.if ${year=%Y month=%m day=%d:L:gmtime=1459494000} != "year=2016 month=04 day=01" 174d5e0a182SSimon J. Gerraty. error 175d5e0a182SSimon J. Gerraty.endif 176d5e0a182SSimon J. Gerraty# Slightly contorted syntax to convert a UTC timestamp from an expression to a 177d5e0a182SSimon J. Gerraty# formatted timestamp. 178d5e0a182SSimon J. Gerraty.if ${%Y%m%d:L:${gmtime=${:U1459494000}:L}} != "20160401" 179d5e0a182SSimon J. Gerraty. error 180d5e0a182SSimon J. Gerraty.endif 181d5e0a182SSimon J. Gerraty 182d5e0a182SSimon J. Gerraty 18306b9b3e0SSimon J. Gerratyall: 184