You could also adjust the timezone value $TZ This will adjust your current session to give you a variation of the clock based on the real time your server holds (actually against GMT / UTC / Zulu depending how you see it)
So if your time zone is:-
echo $TZ
GMT0BST
You can set it to:-
TZ=GMT1BST
Then run your date commands to get the values and then reset the original TZ before running touch. You will probably have a different TZ to mine, but add one to the number early on.
Orig_TZ="$TZ"
TZ=GMT1BST # Adjust to suit, of course
date '+%m %d %H'|read MM DD HH
TZ=$Orig_TZ
touch -t ${MM}${DD}${HH}00 ${SSFILE}
to set HOURAGO turns a 2 digit hour string into a single digit hour string for any time before 11am (thereby producing a -t option string in the wrong format). And even if HOURAGO was set to 23 instead of -1, the HH and possibly DD and MM values will be off as well. And, if the code is fixed to set HOURAGO to 23 and 00 through 09 (rather than -1 and 0 through nine), it needs to use CCYY in case the script is run in the 1st hour of New Year's day by a cron job (or some poor operator stuck in the office on New Year's Day's early morning shift) or the touch (after adjusting MM and DD will set the timestamps to the 11pm hour of December 31st in the new year instead of in the previous year).
And, using multiple calls to the date utility to get individual portions of the desired date is a recipe for generating wrong times that are difficult to diagnose. If the calls to date happen during different seconds on the clock, the minute, hour, day, month, and year could all be off. For example, if the first of the calls to date in this example starts just before midnight on December 31th, the resulting calculated date (before subtracting 1 from the hour) could be any of:
12312359
01312359
01012359
01010059
or
01010000
With scheduling delays the differences could be even more unpredictable. (In other words; NEVER use multiple calls to date to get various pieces of what is supposed to be a single timestamp.)
Robin's (rbatte1) proposal will work in the US except for a couple of hours twice a year (on days when we switch to and from daylight savings time). Using TZ=GMT1BST will be off not only on daylight savings time switch days, but will also be off by an hour all day on days between the switch to daylight savings time in the UK and the switch to daylight savings time in the US. This can be fixed outside the US by using the full capabilities of the TZ variable format stdoffset[dst[offset[,start[/time],end[/time]]] which can specify not only the names of the standard and daylight savings time zone abbreviations ( std and dst , respectively, and the offset from Greenwich, but also the start and end dates for daylight savings time, and the time s at which the shift takes place; but it still leaves you with a result that is an hour off for a couple of hours around the switchover two times per year in areas that observe daylight savings time.
To accurately get the time one hour ago at all times of the day every day of the year on Solaris systems that don't have the GNU date utility installed when you are in an area of the world where daylight savings time is observed, you can either use perl (as has been shown in these forums many times before) or write a simple C program to get the current number of seconds since the Epoch, subtract 3600 (the number of seconds in an hour) and format that value using a function to print a seconds since the Epoch value that adjusts for the current system default timezone as modified by the setting of TZ. In C, the following should work:
#include <libgen.h>
#include <stdio.h>
#include <time.h>
int
main(int argc, char *argv[]) {
time_t modtime; // modified seconds since the Epoch
char out[1024]; // output buffer
struct tm *timep; // broken down adjusted local time
// Verify number of arguments
if(argc != 3) {
(void)fprintf(stderr, "Usage: %s offset fmt\n",
basename(argv[0]));
return 1;
}
// Get desired time as a value in seconds since the Epoch as
// specified by the "offset" operand.
modtime = time(NULL) + atol(argv[1]);
// Convert that time to a struct tm as adjusted by current $TZ setting.
timep = localtime(&modtime);
// Format the output as specified by the given "fmt" operand.
(void)strftime(out, sizeof(out) - 1, argv[2], timep);
(void)printf("%s", out);
}
although the above code doesn't check for errors (other than wrong number of arguments. For this to be put into a production environment; at the least, the calls to atol(), localtime(), and strftime() should be checked for errors. The output is also unspecified if the fmt operand given causes strftime() to produce more that 1024 bytes of output (including the terminating NUL byte).
If you compile the above code and mv the a.out to a file named timeoffset , the following commands will create files with timestamps set to the time one day ago and one hour ago, respectively:
Thanks Scott and Don for pointing out the problems with date calculations!
Another thanks to Don for a general C solution!
Here is a (not so general) native Perl solution