Skip to content

Commit 1b1347d

Browse files
author
maechler
committed
format.POSIXlt tweaks: new 4th arg digits in .Internal(format.POSIXlt(.., digits))
git-svn-id: https://svn.r-project.org/R/trunk@87427 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent d6042c3 commit 1b1347d

File tree

5 files changed

+47
-23
lines changed

5 files changed

+47
-23
lines changed

src/library/base/R/datetime.R

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,12 @@ format.POSIXlt <- function(x, format = "", usetz = FALSE,
405405
else paste0("%Y-%m-%d %H:%M:%OS", np)
406406
}
407407
if(!missing(digits) && !is.null(digits) && digits != getOption("digits.secs", 0L) &&
408-
any(OS. <- grepl("%OS[^0-9]", format))) { ## use digits to find n to use for "%OS<n>"
408+
any(OS. <- grepl("%OS($|[^0-9])", format))) {
409409
x_ <- if(nf == 1L) x else x[OS.]
410-
np <- useDig(x_$sec, digits)
411-
format[OS.] <- gsub("%OS([^0-9])", paste0("%OS", np, "\\1"), format[OS.])
410+
digits <- useDig(x_$sec, digits)
412411
}
413412
## C code in do_formatPOSIXlt() *does* recycle {x, format} as needed:
414-
.Internal(format.POSIXlt(x, format, usetz))
413+
.Internal(format.POSIXlt(x, format, usetz, digits))
415414
}
416415

417416
## prior to 2.9.0 the same as format.POSIXlt.

src/main/datetime.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ static int likely_strftime_overflow (stm *tm)
304304
We could avoid loops altogether by computing how many leap years
305305
there are between 1900 + tm->tm_year and 1900.
306306
307-
This will fix up tm_yday and tm_wday.
307+
This will fix up tm->tm_yday and tm->tm_wday.
308308
309309
Used in timegm00 (possibly) and guess_offset in PATH 1),
310310
POSIXlt2D and do_balancePOSIXlt
@@ -790,7 +790,7 @@ static void prepare_dummy_reset_tz(tzset_info *si)
790790
si->settz = FALSE;
791791
si->end_context_on_reset = FALSE;
792792
}
793-
793+
794794
static Rboolean set_tz(const char *tz, tzset_info *si)
795795
{
796796
si->settz = FALSE;
@@ -1264,6 +1264,7 @@ attribute_hidden SEXP do_formatPOSIXlt(SEXP call, SEXP op, SEXP args, SEXP env)
12641264
int UseTZ = asLogical(CADDR(args));
12651265
if(UseTZ == NA_LOGICAL)
12661266
error(_("invalid '%s' argument"), "usetz");
1267+
int digits = asInteger(CADDDR(args)); // checked for NA below
12671268
SEXP tz = getAttrib(x, install("tzone"));
12681269
if(!isNull(tz) && !isString(tz))
12691270
error(_("invalid '%s'"), "attr(x, \"tzone\")");
@@ -1375,7 +1376,7 @@ attribute_hidden SEXP do_formatPOSIXlt(SEXP call, SEXP op, SEXP args, SEXP env)
13751376
ns = *(p + 3) - '0';
13761377
if(ns < 0 || ns > 9) { /* not a digit */
13771378
if (ns0 == -1) {
1378-
ns0 = asInteger(GetOption1(install("digits.secs")));
1379+
ns0 = digits;
13791380
if(ns0 == NA_INTEGER) ns0 = 0;
13801381
}
13811382
ns = ns0;

src/main/names.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ FUNTAB R_FunTab[] =
838838
{"Sys.time", do_systime, 0, 11, 0, {PP_FUNCALL, PREC_FN, 0}},
839839
{"as.POSIXct", do_asPOSIXct, 0, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
840840
{"as.POSIXlt", do_asPOSIXlt, 0, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
841-
{"format.POSIXlt",do_formatPOSIXlt,0, 11, 3, {PP_FUNCALL, PREC_FN, 0}},
841+
{"format.POSIXlt",do_formatPOSIXlt,0, 11, 4, {PP_FUNCALL, PREC_FN, 0}},
842842
{"strptime", do_strptime, 0, 11, 3, {PP_FUNCALL, PREC_FN, 0}},
843843
{"Date2POSIXlt",do_D2POSIXlt, 0, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
844844
{"POSIXlt2Date",do_POSIXlt2D, 0, 11, 1, {PP_FUNCALL, PREC_FN, 0}},

tests/datetime5.R

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,20 @@ cat(format(dt2, "%Y: %U %V %W"), sep = "\n")
3333
paste0("%Y-%m-%d", c("", paste0(" %H:%M:%OS", c("", 0, 1, 6, 9, 11))))))
3434
weekD <- seq(as.Date("2020-04-01"), by = "weeks", length.out = 5 * length(fmt)) ; joff <- (0:4)*length(fmt)
3535
weekPlt <- as.POSIXlt(weekD, tz = "UTC")
36-
(Lf1 <- split(f1 <- format(weekPlt, format = fmt), fmt))
37-
(Lf. <- split(f. <- format(weekPlt + 0.25, format = fmt), fmt))
38-
(Lf3 <- split(f3 <- format(weekPlt + 0.25, format = fmt, digits = 3), fmt))
39-
stopifnot(f3[2L+joff] == f3[3L+joff],
40-
grepl("^00:00:00.25 in 202[01]", f3[2L+joff]))
41-
## digits = 3 had no effect on "%OS "
36+
week.25 <- weekPlt + 0.25
37+
(Lf1 <- split(f1 <- format(weekPlt, format = fmt), fmt))
38+
(Lf. <- split(f. <- format(week.25, format = fmt), fmt))
39+
(Lf3 <- split(f3 <- format(week.25, format = fmt, digits = 3), fmt))
40+
stopifnot(exprs = {
41+
f3[2L+joff] == f3[3L+joff]
42+
grepl("^00:00:00.25 in 202[01]", f3[2L+joff])
43+
grepl("00:00:00.25$", f3[5L+joff]) # (was wrong shortly)
44+
## '%OS<n>' overrules 'digits' {was true forever}
45+
format(week.25, format = "%OS0", digits = 3) == "00"
46+
format(week.25, format = "%OS1", digits = 3) == "00.2"
47+
})
48+
## digits = 3 had no effect on "%OS " in R <= 4.4
49+
## NB: 2nd %OS _never_ worked (internal C code) -- TODO: fix or doc
50+
unique(fOO_ <- format(week.25, "%OS|%OS3|"))
51+
unique(fOO_1 <- format(week.25, "%OS3|%OS1|%OS3|"))
52+

tests/datetime5.Rout.save

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
R Under development (unstable) (2024-12-03 r87418) -- "Unsuffered Consequences"
2+
R Under development (unstable) (2024-12-05 r87423) -- "Unsuffered Consequences"
33
Copyright (C) 2024 The R Foundation for Statistical Computing
44
Platform: x86_64-pc-linux-gnu
55

@@ -98,7 +98,8 @@ Type 'q()' to quit R.
9898
[10] "%Y-%m-%d %H:%M:%OS11"
9999
> weekD <- seq(as.Date("2020-04-01"), by = "weeks", length.out = 5 * length(fmt)) ; joff <- (0:4)*length(fmt)
100100
> weekPlt <- as.POSIXlt(weekD, tz = "UTC")
101-
> (Lf1 <- split(f1 <- format(weekPlt, format = fmt), fmt))
101+
> week.25 <- weekPlt + 0.25
102+
> (Lf1 <- split(f1 <- format(weekPlt, format = fmt), fmt))
102103
[[1]]
103104
[1] "2020-04-01" "2020-06-10" "2020-08-19" "2020-10-28" "2021-01-06"
104105

@@ -139,7 +140,7 @@ $`%Y-%m-%d %H:%M:%OS9`
139140
[3] "2020-10-14 00:00:00.000000" "2020-12-23 00:00:00.000000"
140141
[5] "2021-03-03 00:00:00.000000"
141142

142-
> (Lf. <- split(f. <- format(weekPlt + 0.25, format = fmt), fmt))
143+
> (Lf. <- split(f. <- format(week.25, format = fmt), fmt))
143144
[[1]]
144145
[1] "2020-04-01 00:00:00" "2020-06-10 00:00:00" "2020-08-19 00:00:00"
145146
[4] "2020-10-28 00:00:00" "2021-01-06 00:00:00"
@@ -181,7 +182,7 @@ $`%Y-%m-%d %H:%M:%OS9`
181182
[3] "2020-10-14 00:00:00.250000" "2020-12-23 00:00:00.250000"
182183
[5] "2021-03-03 00:00:00.250000"
183184

184-
> (Lf3 <- split(f3 <- format(weekPlt + 0.25, format = fmt, digits = 3), fmt))
185+
> (Lf3 <- split(f3 <- format(week.25, format = fmt, digits = 3), fmt))
185186
[[1]]
186187
[1] "2020-04-01 00:00:00.25" "2020-06-10 00:00:00.25" "2020-08-19 00:00:00.25"
187188
[4] "2020-10-28 00:00:00.25" "2021-01-06 00:00:00.25"
@@ -198,8 +199,8 @@ $`%Y-%m-%d`
198199
[1] "2020-04-22" "2020-07-01" "2020-09-09" "2020-11-18" "2021-01-27"
199200

200201
$`%Y-%m-%d %H:%M:%OS`
201-
[1] "2020-04-29 00:00:00" "2020-07-08 00:00:00" "2020-09-16 00:00:00"
202-
[4] "2020-11-25 00:00:00" "2021-02-03 00:00:00"
202+
[1] "2020-04-29 00:00:00.25" "2020-07-08 00:00:00.25" "2020-09-16 00:00:00.25"
203+
[4] "2020-11-25 00:00:00.25" "2021-02-03 00:00:00.25"
203204

204205
$`%Y-%m-%d %H:%M:%OS0`
205206
[1] "2020-05-06 00:00:00" "2020-07-15 00:00:00" "2020-09-23 00:00:00"
@@ -223,7 +224,19 @@ $`%Y-%m-%d %H:%M:%OS9`
223224
[3] "2020-10-14 00:00:00.250000" "2020-12-23 00:00:00.250000"
224225
[5] "2021-03-03 00:00:00.250000"
225226

226-
> stopifnot(f3[2L+joff] == f3[3L+joff],
227-
+ grepl("^00:00:00.25 in 202[01]", f3[2L+joff]))
228-
> ## digits = 3 had no effect on "%OS "
227+
> stopifnot(exprs = {
228+
+ f3[2L+joff] == f3[3L+joff]
229+
+ grepl("^00:00:00.25 in 202[01]", f3[2L+joff])
230+
+ grepl("00:00:00.25$", f3[5L+joff]) # (was wrong shortly)
231+
+ ## '%OS<n>' overrules 'digits' {was true forever}
232+
+ format(week.25, format = "%OS0", digits = 3) == "00"
233+
+ format(week.25, format = "%OS1", digits = 3) == "00.2"
234+
+ })
235+
> ## digits = 3 had no effect on "%OS " in R <= 4.4
236+
> ## NB: 2nd %OS _never_ worked (internal C code) -- TODO: fix or doc
237+
> unique(fOO_ <- format(week.25, "%OS|%OS3|"))
238+
[1] "00|003|"
239+
> unique(fOO_1 <- format(week.25, "%OS3|%OS1|%OS3|"))
240+
[1] "00.250|001|003|"
241+
>
229242
>

0 commit comments

Comments
 (0)