summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Somers <brian@FreeBSD.org>2000-06-15 16:08:04 +0000
committerBrian Somers <brian@FreeBSD.org>2000-06-15 16:08:04 +0000
commit33e0743f832d3aaea137a9f7c77d02b3ad346e15 (patch)
treeaec313896d285a183a7ac24880a598043f60601a
parent64a5bc137e87976a06b49ad960865c6f59b05b37 (diff)
Notes
-rw-r--r--bin/date/date.125
-rw-r--r--bin/date/vary.c217
2 files changed, 154 insertions, 88 deletions
diff --git a/bin/date/date.1 b/bin/date/date.1
index 3beaac6b3298..4e4e31268a6a 100644
--- a/bin/date/date.1
+++ b/bin/date/date.1
@@ -122,7 +122,9 @@ or backwards according to the remaining string, otherwise the relevant
part of the date is set. The date can be adjusted as many times as
required using these flags. Flags are processed in the order given.
.Pp
-Seconds are in the range 0-59, minutes are in the range 0-59, hours are
+When setting values
+.Pq rather than adjusting them ,
+seconds are in the range 0-59, minutes are in the range 0-59, hours are
in the range 1-12, month days are in the range 1-31, week days are in the
range 0-6 (Sun-Sat), months are in the range 1-12 (Jan-Dec) and years are
in the range 80-38 or 1980-2038.
@@ -146,6 +148,27 @@ will be put forwards (or backwards) to the next (previous) date that
matches the given week day or month. This will not adjust the date
if the given week day or month is the same as the current one.
.Pp
+When a date is adjusted to a specific value or in units greater than hours,
+daylight savings time considerations are ignored.
+Adjustments in units of hours or less honour daylight savings time.
+So, assuming the current date is March 26, 0:30 and that the DST adjustment
+means that the clock goes forward at 01:00 to 02:00, using
+.Fl v No +1H
+will adjust the date to March 26, 2:30.
+Likewise, if the date is October 29, 0:30 and the DST adjustment means that
+the clock goes back at 02:00 to 01:00, using
+.Fl v No +3H
+will be necessary to reach October 20, 2:30.
+.Pp
+When the date is adjusted to a specific value that doesn't actually exist
+.Pq for example March 26, 1:30 BST 2000 ,
+the date will be silently adjusted forwards in units of one hour until it
+reaches a valid time.
+When the date is adjusted to a specific value that occurs twice
+.Pq for example October 29, 1:30 2000 ,
+the resulting timezone will be set so that the date matches the earlier of
+the two times.
+.Pp
Refer to the examples below for further details.
.El
.Pp
diff --git a/bin/date/vary.c b/bin/date/vary.c
index 12faf8a201ad..7fba4221116b 100644
--- a/bin/date/vary.c
+++ b/bin/date/vary.c
@@ -41,7 +41,7 @@ struct trans {
static struct trans trans_mon[] = {
{ 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" },
- { 5, "may" }, { 6, "june" }, { 7, "july" }, { 8, "august" },
+ { 5, "may"}, { 6, "june" }, { 7, "july" }, { 8, "august" },
{ 9, "september" }, { 10, "october" }, { 11, "november" }, { 12, "december" },
{ -1, NULL }
};
@@ -53,6 +53,19 @@ static struct trans trans_wday[] = {
};
static char digits[] = "0123456789";
+static int adjhour(struct tm *, char, int, int);
+
+static int
+domktime(struct tm *t, char type)
+{
+ time_t ret;
+
+ while ((ret = mktime(t)) == -1 && t->tm_year > 68 && t->tm_year < 138)
+ /* While mktime() fails, adjust by an hour */
+ adjhour(t, type == '-' ? type : '+', 1, 0);
+
+ return ret;
+}
static int
trans(const struct trans t[], const char *arg)
@@ -112,7 +125,7 @@ daysinmonth(const struct tm *t)
static int
-adjyear(struct tm *t, char type, int val)
+adjyear(struct tm *t, char type, int val, int mk)
{
switch (type) {
case '+':
@@ -129,45 +142,51 @@ adjyear(struct tm *t, char type, int val)
t->tm_year -= 1900; /* struct tm holds years since 1900 */
break;
}
- return mktime(t) != -1;
+ return !mk || domktime(t, type) != -1;
}
static int
-adjmon(struct tm *t, char type, int val, int istext)
+adjmon(struct tm *t, char type, int val, int istext, int mk)
{
if (val < 0)
return 0;
switch (type) {
case '+':
- if (istext)
+ if (istext) {
if (val <= t->tm_mon)
val += 11 - t->tm_mon; /* early next year */
else
val -= t->tm_mon + 1; /* later this year */
- if (!adjyear(t, '+', (t->tm_mon + val) / 12))
- return 0;
- val %= 12;
- t->tm_mon += val;
- if (t->tm_mon > 11)
- t->tm_mon -= 12;
+ }
+ if (val) {
+ if (!adjyear(t, '+', (t->tm_mon + val) / 12, 0))
+ return 0;
+ val %= 12;
+ t->tm_mon += val;
+ if (t->tm_mon > 11)
+ t->tm_mon -= 12;
+ }
break;
case '-':
- if (istext)
+ if (istext) {
if (val-1 > t->tm_mon)
val = 13 - val + t->tm_mon; /* later last year */
else
val = t->tm_mon - val + 1; /* early this year */
- if (!adjyear(t, '-', val / 12))
- return 0;
- val %= 12;
- if (val > t->tm_mon) {
- if (!adjyear(t, '-', 1))
+ }
+ if (val) {
+ if (!adjyear(t, '-', val / 12, 0))
return 0;
- val -= 12;
+ val %= 12;
+ if (val > t->tm_mon) {
+ if (!adjyear(t, '-', 1, 0))
+ return 0;
+ val -= 12;
+ }
+ t->tm_mon -= val;
}
- t->tm_mon -= val;
break;
default:
@@ -176,13 +195,14 @@ adjmon(struct tm *t, char type, int val, int istext)
t->tm_mon = --val;
}
- return mktime(t) != -1;
+ return !mk || domktime(t, type) != -1;
}
static int
-adjday(struct tm *t, char type, int val)
+adjday(struct tm *t, char type, int val, int mk)
{
int mdays;
+
switch (type) {
case '+':
while (val) {
@@ -190,7 +210,7 @@ adjday(struct tm *t, char type, int val)
if (val > mdays - t->tm_mday) {
val -= mdays - t->tm_mday + 1;
t->tm_mday = 1;
- if (!adjmon(t, '+', 1, 0))
+ if (!adjmon(t, '+', 1, 0, 0))
return 0;
} else {
t->tm_mday += val;
@@ -203,7 +223,7 @@ adjday(struct tm *t, char type, int val)
if (val >= t->tm_mday) {
val -= t->tm_mday;
t->tm_mday = 1;
- if (!adjmon(t, '-', 1, 0))
+ if (!adjmon(t, '-', 1, 0, 0))
return 0;
t->tm_mday = daysinmonth(t);
} else {
@@ -219,11 +239,11 @@ adjday(struct tm *t, char type, int val)
break;
}
- return mktime(t) != -1;
+ return !mk || domktime(t, type) != -1;
}
static int
-adjwday(struct tm *t, char type, int val, int istext)
+adjwday(struct tm *t, char type, int val, int istext, int mk)
{
if (val < 0)
return 0;
@@ -236,54 +256,62 @@ adjwday(struct tm *t, char type, int val, int istext)
else
val -= t->tm_wday; /* later this week */
else
- val *= 7; /* "-W +5" == "5 weeks in the future" */
- return adjday(t, '+', val);
+ val *= 7; /* "-v+5w" == "5 weeks in the future" */
+ return !val || adjday(t, '+', val, mk);
case '-':
- if (istext)
+ if (istext) {
if (val > t->tm_wday)
val = 7 - val + t->tm_wday; /* later last week */
else
val = t->tm_wday - val; /* early this week */
- else
- val *= 7; /* "-W -5" == "5 weeks ago" */
- return adjday(t, '-', val);
+ } else
+ val *= 7; /* "-v-5w" == "5 weeks ago" */
+ return !val || adjday(t, '-', val, mk);
default:
if (val < t->tm_wday)
- return adjday(t, '-', t->tm_wday - val);
+ return adjday(t, '-', t->tm_wday - val, mk);
else if (val > 6)
return 0;
else if (val > t->tm_wday)
- return adjday(t, '+', val - t->tm_wday);
+ return adjday(t, '+', val - t->tm_wday, mk);
}
return 1;
}
static int
-adjhour(struct tm *t, char type, int val)
+adjhour(struct tm *t, char type, int val, int mk)
{
if (val < 0)
return 0;
switch (type) {
case '+':
- if (!adjday(t, '+', (t->tm_hour + val) / 24))
- return 0;
- val %= 24;
- t->tm_hour += val;
- if (t->tm_hour > 23)
- t->tm_hour -= 24;
+ if (val) {
+ int days;
+
+ days = (t->tm_hour + val) / 24;
+ val %= 24;
+ t->tm_hour += val;
+ t->tm_hour %= 24;
+ if (!adjday(t, '+', days, 0))
+ return 0;
+ }
break;
case '-':
- if (!adjday(t, '-', val / 24))
- return 0;
- val %= 24;
- if (val > t->tm_hour) {
- if (!adjday(t, '-', 1))
+ if (val) {
+ int days;
+
+ days = val / 24;
+ val %= 24;
+ if (val > t->tm_hour) {
+ days++;
+ val -= 24;
+ }
+ t->tm_hour -= val;
+ if (!adjday(t, '-', days, 0))
return 0;
- val -= 24;
}
- t->tm_hour -= val;
break;
default:
@@ -292,35 +320,39 @@ adjhour(struct tm *t, char type, int val)
t->tm_hour = val;
}
- return mktime(t) != -1;
+ return !mk || domktime(t, type) != -1;
}
static int
-adjmin(struct tm *t, char type, int val)
+adjmin(struct tm *t, char type, int val, int mk)
{
if (val < 0)
return 0;
switch (type) {
case '+':
- if (!adjhour(t, '+', (t->tm_min + val) / 60))
- return 0;
- val %= 60;
- t->tm_min += val;
- if (t->tm_min > 59)
- t->tm_min -= 60;
+ if (val) {
+ if (!adjhour(t, '+', (t->tm_min + val) / 60, 0))
+ return 0;
+ val %= 60;
+ t->tm_min += val;
+ if (t->tm_min > 59)
+ t->tm_min -= 60;
+ }
break;
case '-':
- if (!adjhour(t, '-', val / 60))
- return 0;
- val %= 60;
- if (val > t->tm_min) {
- if (!adjhour(t, '-', 1))
+ if (val) {
+ if (!adjhour(t, '-', val / 60, 0))
return 0;
- val -= 60;
+ val %= 60;
+ if (val > t->tm_min) {
+ if (!adjhour(t, '-', 1, 0))
+ return 0;
+ val -= 60;
+ }
+ t->tm_min -= val;
}
- t->tm_min -= val;
break;
default:
@@ -329,35 +361,39 @@ adjmin(struct tm *t, char type, int val)
t->tm_min = val;
}
- return mktime(t) != -1;
+ return !mk || domktime(t, type) != -1;
}
static int
-adjsec(struct tm *t, char type, int val)
+adjsec(struct tm *t, char type, int val, int mk)
{
if (val < 0)
return 0;
switch (type) {
case '+':
- if (!adjmin(t, '+', (t->tm_sec + val) / 60))
- return 0;
- val %= 60;
- t->tm_sec += val;
- if (t->tm_sec > 59)
- t->tm_sec -= 60;
+ if (val) {
+ if (!adjmin(t, '+', (t->tm_sec + val) / 60, 0))
+ return 0;
+ val %= 60;
+ t->tm_sec += val;
+ if (t->tm_sec > 59)
+ t->tm_sec -= 60;
+ }
break;
case '-':
- if (!adjmin(t, '-', val / 60))
- return 0;
- val %= 60;
- if (val > t->tm_sec) {
- if (!adjmin(t, '-', 1))
+ if (val) {
+ if (!adjmin(t, '-', val / 60, 0))
return 0;
- val -= 60;
+ val %= 60;
+ if (val > t->tm_sec) {
+ if (!adjmin(t, '-', 1, 0))
+ return 0;
+ val -= 60;
+ }
+ t->tm_sec -= val;
}
- t->tm_sec -= val;
break;
default:
@@ -366,7 +402,7 @@ adjsec(struct tm *t, char type, int val)
t->tm_sec = val;
}
- return mktime(t) != -1;
+ return !mk || domktime(t, type) != -1;
}
const struct vary *
@@ -389,15 +425,18 @@ vary_apply(const struct vary *v, struct tm *t)
if (len < 2)
return v;
+ if (type == '\0')
+ t->tm_isdst = -1;
+
if (strspn(arg, digits) != len-1) {
val = trans(trans_wday, arg);
if (val != -1) {
- if (!adjwday(t, type, val, 1))
+ if (!adjwday(t, type, val, 1, 1))
return v;
} else {
val = trans(trans_mon, arg);
if (val != -1) {
- if (!adjmon(t, type, val, 1))
+ if (!adjmon(t, type, val, 1, 1))
return v;
} else
return v;
@@ -408,31 +447,35 @@ vary_apply(const struct vary *v, struct tm *t)
switch (which) {
case 'S':
- if (!adjsec(t, type, val))
+ if (!adjsec(t, type, val, 1))
return v;
break;
case 'M':
- if (!adjmin(t, type, val))
+ if (!adjmin(t, type, val, 1))
return v;
break;
case 'H':
- if (!adjhour(t, type, val))
+ if (!adjhour(t, type, val, 1))
return v;
break;
case 'd':
- if (!adjday(t, type, val))
+ t->tm_isdst = -1;
+ if (!adjday(t, type, val, 1))
return v;
break;
case 'w':
- if (!adjwday(t, type, val, 0))
+ t->tm_isdst = -1;
+ if (!adjwday(t, type, val, 0, 1))
return v;
break;
case 'm':
- if (!adjmon(t, type, val, 0))
+ t->tm_isdst = -1;
+ if (!adjmon(t, type, val, 0, 1))
return v;
break;
case 'y':
- if (!adjyear(t, type, val))
+ t->tm_isdst = -1;
+ if (!adjyear(t, type, val, 1))
return v;
break;
default: