I have DateTime structure for an old data format that I don't have access to any specs for. There is a field which indicates the datetime of the the data, but it isn't in any format I recognize. It appears to be stored as a 32-bit integer, that increments by 20 for each day. Has anyone ever run across something like this?
EDIT:
Example: 1088631936 DEC = 80 34 E3 40 00 00 00 00 HEX = 09/07/2007
EDIT:
First off, sorry for the delay. I had hoped to do stuff over the weekend, but was unable to.
Second, this date format is weirder than I initially thought. It appears to be some sort of exponential or logarithmic method, as the dates do not change at an increasing rate.
Third, the defunct app that I have for interpreting these values only shows the date portion, so I don't know what the time portion is.
Example data:
(Hex values are big-endian, dates are mm/dd/yyyy)
0x40000000 = 01/01/1900
0x40010000 = 01/01/1900
0x40020000 = 01/01/1900
0x40030000 = 01/01/1900
0x40040000 = 01/01/1900
0x40050000 = 01/01/1900
0x40060000 = 01/01/1900
0x40070000 = 01/01/1900
0x40080000 = 01/02/1900
0x40090000 = 01/02/1900
0x400A0000 = 01/02/1900
0x400B0000 = 01/02/1900
0x400C0000 = 01/02/1900
0x400D0000 = 01/02/1900
0x400E0000 = 01/02/1900
0x400F0000 = 01/02/1900
0x40100000 = 01/03/1900
0x40110000 = 01/03/1900
0x40120000 = 01/03/1900
0x40130000 = 01/03/1900
0x40140000 = 01/04/1900
0x40150000 = 01/04/1900
0x40160000 = 01/04/1900
0x40170000 = 01/04/1900
0x40180000 = 01/05/1900
0x40190000 = 01/05/1900
0x401A0000 = 01/05/1900
0x401B0000 = 01/05/1900
0x401C0000 = 01/06/1900
0x401D0000 = 01/06/1900
0x401E0000 = 01/06/1900
0x401F0000 = 01/06/1900
0x40200000 = 01/07/1900
0x40210000 = 01/07/1900
0x40220000 = 01/08/1900
0x40230000 = 01/08/1900
....
0x40800000 = 05/26/1901
0x40810000 = 06/27/1901
0x40820000 = 07/29/1901
....
0x40D00000 = 11/08/1944
0x40D10000 = 08/29/1947
EDIT: I finally figured this out, but since I've already given up the points for the bounty, I'll hold off on the solution in case anyone wants to give it a shot.
BTW, there is no time component to this, it is purely for storing dates.
It's not integer, it's a 32 bit floating point number. I haven't quite worked out the format yet, it's not IEEE.
Edit: got it. 1 bit sign, 11 bit exponent with an offset of 0x3ff, and 20 bit mantissa with an implied bit to the left. In C, assuming positive numbers only:
double offset = pow(2, (i >> 20) - 0x3ff) * (((i & 0xfffff) + 0x100000) / (double) 0x100000);
This yields 0x40000000 = 2.0, so the starting date must be 12/30/1899.
Edit again: since you were so kind as to accept my answer, and you seem concerned about speed, I thought I'd refine this a little. You don't need the fractional part of the real number, so we can convert straight to integer using only bitwise operations. In Python this time, complete with test results. I've included some intermediate values for better readability. In addition to the restriction of no negative numbers, this version might have problems when the exponent goes over 19, but this should keep you good until the year 3335.
>>> def IntFromReal32(i):
exponent = (i >> 20) - 0x3ff
mantissa = (i & 0xfffff) + 0x100000
return mantissa >> (20 - exponent)
>>> testdata = range(0x40000000,0x40240000,0x10000) + range(0x40800000,0x40830000,0x10000) + [1088631936]
>>> from datetime import date,timedelta
>>> for i in testdata:
print "0x%08x" % i, date(1899,12,30) + timedelta(IntFromReal32(i))
0x40000000 1900-01-01
0x40010000 1900-01-01
0x40020000 1900-01-01
0x40030000 1900-01-01
0x40040000 1900-01-01
0x40050000 1900-01-01
0x40060000 1900-01-01
0x40070000 1900-01-01
0x40080000 1900-01-02
0x40090000 1900-01-02
0x400a0000 1900-01-02
0x400b0000 1900-01-02
0x400c0000 1900-01-02
0x400d0000 1900-01-02
0x400e0000 1900-01-02
0x400f0000 1900-01-02
0x40100000 1900-01-03
0x40110000 1900-01-03
0x40120000 1900-01-03
0x40130000 1900-01-03
0x40140000 1900-01-04
0x40150000 1900-01-04
0x40160000 1900-01-04
0x40170000 1900-01-04
0x40180000 1900-01-05
0x40190000 1900-01-05
0x401a0000 1900-01-05
0x401b0000 1900-01-05
0x401c0000 1900-01-06
0x401d0000 1900-01-06
0x401e0000 1900-01-06
0x401f0000 1900-01-06
0x40200000 1900-01-07
0x40210000 1900-01-07
0x40220000 1900-01-08
0x40230000 1900-01-08
0x40800000 1901-05-26
0x40810000 1901-06-27
0x40820000 1901-07-29
0x40e33480 2007-09-07
Are you sure that values correspond to 09/07/2007?
I ask because 1088631936 are the number of seconds since Linux (et al) zero date: 01/01/1970 00:00:00 to 06/30/2004 21:45:36.
Seems to me reasonable to think the value are seconds since this usual zero date.
Edit: I know it is very possible for this not to be the correct answer. It is just one approach (a valid one) but I think more info is needed (see the comments). Editing this (again) to bring the question to the front in the hope of somebody else to answer it or give ideas. Me: with a fairness, sportive and sharing spirit :D
I'd say that vmarquez is close.
Here are dates 2009-3-21 and 2009-3-22 as unix epochtime:
In [8]: time.strftime("%s", (2009, 3, 21, 1, 1, 0, 0,0,0))
Out[8]: '1237590060'
In [9]: time.strftime("%s", (2009, 3, 22, 1, 1, 0, 0,0,0))
Out[9]: '1237676460'
And here they are in hex:
In [10]: print("%0x %0x" % (1237590060, 1237676460))
49c4202c 49c571ac
If you take only first 5 digits, the growth is 21. Which kinda matches your format, neg?
Some context would be useful. If your data file looks something, literally or at least figuratively, like this file, vmarquez is on the money.
http://www.slac.stanford.edu/comp/net/bandwidth-tests/eventanalysis/all_100days_sep04/node1.niit.pk
That reference is data produced by Available Bandwith Estimation tool (ABwE) -- the curious item is that it actually contains that 1088631936 value as well as the context. That example
date time abw xtr dbcap avabw avxtr avdbcap rtt timestamp
06/30/04 14:43:48 1.000 0.000 1.100 1.042 0.003 1.095 384.387 1088631828
06/30/04 14:45:36 1.100 0.000 1.100 1.051 0.003 1.096 376.408 1088631936
06/30/04 14:47:23 1.000 0.000 1.100 1.043 0.003 1.097 375.196 1088632043
seems to have a seven hour offset from the suggested 21:45:36 time value. (Probably Stanford local, running on Daylight savings time.)
Well, you've only shown us how your program uses 2 of the 8 digits, so we'll have to assume that the other 6 are ignored (because your program could be doing anything it wants with those other digits).
So, we could say that the input format is:
40mn0000
where m and n are two hex digits.
Then, the output is:
01/01/1900 + floor((2^(m+1)-2) + n*2^(m-3)) days
Explanation:
In each example, notice that incrementing n by 1 increases the number of days by 2^(m-3).
Notice that every time n goes from F to 0, m is incremented.
Using these two rules, and playing around with the numbers, you get the equation above.
(Except for floor, which was added because the output doesn't display fractional days).
I suppose you could rewrite this by replacing the two separate hex variables m and n with a single 2-digit hex number H. However, I think that would make the equation a lot uglier.
Related
hi I has date format and I want converted to correct GMT date :
<YYMMDDhhmmssNNN><C|D|G|H>
Sample value on that date:
210204215026000C
I get this explanation for part NNN :
NNN If flag is C or D then NNN is the number of hours relativeto GMT,
if flag is G or H, NNN is the number of quarter hours relative to GMT
C|D|G|H C and G = Ahead of GMT, D and H = Behind GMT
but I did not get how number of hours relative to GMT can present on 3 digits ? it should be in 2 digit as i knew the offset for hours related to GMT is from 0 to 23 , and also what quarter hours relative to GMT mean ?
I want to use Scala or Java.
I don’t know why they set 3 digits aside for the offset. I agree with you that 2 digits suffice for all cases. Maybe they just wanted to be very sure they would never run of out space, and maybe they even overdid this a bit. 3 digits is not a problem as long as the actual values are within the range that java.time.ZoneOffset can handle, +/-18 hours. In your example NNN is 000, so 0 hours from GMT, which certainly is OK and trivial to handle.
A quarter hour is a quarter of an hour. As Salman A mentioned in a comment, 22 quarter hours ahead of Greenwich means an offset of +05:30, currently used in Sri Lanka and India. If the producer of the string wants to use this option, they can give numbers up to 72 (still comfortably within 2 digits). 18 * 4 = 72, so 18 hours equals 72 quarter hours. To imagine a situation where 2 digits would be too little, think an offset of 25 hours. I wouldn’t think it realistic, on the other hand no one can guarantee that it will never happen.
Java solution: how to parse and convert to GMT time
I am using these constants:
private static final Pattern DATE_PATTERN
= Pattern.compile("(\\d{12})(\\d{3})(\\w)");
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("uuMMddHHmmss");
private static final int SECONDS_IN_A_QUARTER_HOUR
= Math.toIntExact(Duration.ofHours(1).dividedBy(4).getSeconds());
Parse and convert like this:
String sampleValue = "210204215026000C";
Matcher matcher = DATE_PATTERN.matcher(sampleValue);
if (matcher.matches()) {
LocalDateTime ldt = LocalDateTime.parse(matcher.group(1), FORMATTER);
int offsetAmount = Integer.parseInt(matcher.group(2));
char flag = matcher.group(3).charAt(0);
// offset amount denotes either hours or quarter hours
boolean quarterHours = flag == 'G' || flag == 'H';
boolean negative = flag == 'D' || flag == 'H';
if (negative) {
offsetAmount = -offsetAmount;
}
ZoneOffset offset = quarterHours
? ZoneOffset.ofTotalSeconds(offsetAmount * SECONDS_IN_A_QUARTER_HOUR)
: ZoneOffset.ofHours(offsetAmount);
OffsetDateTime dateTime = ldt.atOffset(offset);
OffsetDateTime gmtDateTime = dateTime.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("GMT time: " + gmtDateTime);
}
else {
System.out.println("Invalid value: " + sampleValue);
}
Output is:
GMT time: 2021-02-04T21:50:26Z
I think my code covers all valid cases. You will probably want to validate that the flag is indeed C, D, G or H, and also handle the potential DateTimeException and NumberFormatException from the parsing and creating the ZoneOffset (NumberFormatException should not happen).
In the azure data explorer documentation, there is a lot of supported formats but not the one that i am looking for.
What I need is to format the datetime like "yyyy-MM-dd HH" to set the minutes and seconds as 0
Input datetime
2020-04-21T17:44:27.6825985Z
expected results
2020-04-21 17:00:00
you can use bin() to round down to the hour, and if you still need to remove the datetime parts lower than seconds, you can use substring() (or format_datetime()). e.g.:
print d = datetime(2020-04-21T17:44:27.6825985Z)
| extend h = bin(d, 1h)
| extend h2 = substring(h, 0, 19)
hmm, if you always just want the rest to be 0, can you just use string concatenation?
let d = datetime(2020-04-21T17:44:27.6825985Z);
print strcat(format_datetime(d, "yyyy-MM-dd HH"), ":00:00")
the above code will give you the result of
2020-04-21 17:00:00
In my angular web application, I want to compare two dates to see if a person is less than 18 years old when she/he entered the company. Here is the code I use to do this:
const dayOfBirth = moment(formControl.value, this.dateFormat, true).startOf('day');
const entranceDateControl = this.wizardFormGroup.get('entranceDate');
const entranceDate = moment(entranceDateControl.value, this.dateFormat, true).startOf('day');
// Check validation rule R3: Age is less than 18 compared to entrance date
const difference = moment.duration(Math.abs(entranceDate.diff(dayOfBirth)));
if (difference.years() < 18) {
const validationMessage = this.getValidationMessage('R3', formControlName);
return validationMessage ? validationMessage.message : null;
}
As you can see, I am using startOf('day') to get rid of any time component so that I only handle dates. I use diff() to get the difference between two dates and then duration() to convert the difference to years, months, days, etc. Using this code, the validation message should NOT show when the person is turning 18 years old on the day when she/he entered the company.
Upon testing this, I came across what is, in my opinion, strange behavior. Depending on months and years used, it gave different results. For instance, for these dates it was Ok:
dayOfBirth = 1998-03-01, 1998-04-01, ..., 2000-02-01
entranceDate = 2016-03-01, 2016-04-01, ..., 2018-02-01
But the following dates returned the validation message:
dayOfBirth = 2000-03-01, 2000-04-01, ..., 2002-02-01
entranceDate = 2018-03-01, 2000-04-01, ..., 2020-02-01
After these dates, i.e. using 2002-03-01 and onward, it works again. I also got wrong result for the dates preceding 1998-03-01.
Now, I had a closer look at the Duration object and I noticed that for the times where it was less than 18 years, it had calculated 864 milliseconds less then when it came to the right conclusion that it was 18 years between the dates.
Correct duration
----------------
dayOfBirth = 1998-03-01, 1998-04-01, ..., 2000-02-01
entranceDate = 2016-03-01, 2016-04-01, ..., 2018-02-01
Duration = 568080000000 ms
Wrong duration
--------------
dayOfBirth = 2000-03-01, 2000-04-01, ..., 2002-02-01
entranceDate = 2018-03-01, 2000-04-01, ..., 2020-02-01
Duration = 567993600000 ms
Duration difference
-------------------
568080000000 - 567993600000 = 86400000 ms = 24 hours = 1 day
Has anyone an explanation for this? Can it be considered a bug in momentjs? Any viable workaround for this?
I didn't go into details in moment source code but it seems duration() is playing tricks with you. Simplify the code and rely only on diffas follow and you should be good (at least it seems to work for the samples you provided). And it's easier on the eyes :)
const moment = require('moment')
const dayOfBirth = moment('2000-03-01').startOf('day');
const entranceDate = moment('2018-03-01').startOf('day');
const difference = entranceDate.diff(dayOfBirth, 'years')
if (difference < 18) {
console.log( '<18')
} else {
console.log( '>=18')
}
will output >=18
We have a solution in Delphi that calculates a travel's duration of a given vehicle, for example, 20 minutes, 25 minutes and so on. However, sometimes we have to antecipate the travel's start time, from a specific datetime, for example 09:00 to 08:40. Then, we need to substract a negative value from a TDateTime variable (travel's start), in this case, something like "-00:20". To do this, we multiply the datetime value by -1 (for example MyDiffDateTimeVariable * -1). The output we got is very strange, sometimes we obtain the exactly opposite behavior. In other case, an operation to extract 20 minutes results in a difference of two days from the original datetime.
Here is a sample console application that simulate our situation, with the current outputs, and what we will expected:
program DateTimeSample;
uses
System.SysUtils, System.DateUtils;
var
LDate1: TDateTime;
LDate2: TDateTime;
begin
LDate1 := IncMinute(0, 20);
LDate2 := IncMinute(0, -20);
WriteLn('Date1: ' + DateTimeToStr(LDate1));
// Output = Date1: 30/12/1899 00:20:00 [OK]
WriteLn('Date2: ' + DateTimeToStr(LDate2));
// Output = Date2: 29/12/1899 23:40:00 [OK]
WriteLn('-----');
WriteLn('Date1: ' + DateTimeToStr(LDate1 * -1));
// Output = Date1: 30/12/1899 00:20:00 [Expected 29/12/1899 23:40:00]
WriteLn('Date2: ' + DateTimeToStr(LDate2 * -1));
// Output = Date2: 31/12/1899 23:40:00 [Expected 30/12/1899 00:20:00]
ReadLn;
end.
When you inspect the value casted to double, you can see:
double(LDate1) = 0.0138888888888889
double(LDate2) = -1.98611111111111
Seems like a bug to me, because with today it returns:
double(LDate1) = 43168,0138888889
double(LDate2) = 43167,9861111111
Edit: Hmm, according the documentation, it is not a bug, it is a feature :-)
When working with negative TDateTime values, computations must handle time portion separately. The fractional part reflects the fraction of a 24-hour day without regard to the sign of the TDateTime value. For example, 6:00 A.M. on December 29, 1899 is –1.25, not –1 + 0.25, which would equal –0.75. There are no TDateTime values from –1 through 0.
Karel's answer explains what's happening. Basically, TDateTime is represented as a Double, but that doesn't mean you can work with it in the same way as you normally would a Double value. It's internal structure carries particular semantics that if you don't handle them correctly, you're bound to get some peculiar behaviour.
The key mistake you're making is in taking the negative of a date-time value. This concept doesn't really make sense. Not even if you look at dates in BC, because the calendar system has changed a number of times over the years.
This is the main reason you should favour library routines that deal with the nuances of the internal structure (whatever your platform). In Delphi that means you should use the SysUtils and DateUtils routines for working with dates and times.
You seem to be trying to hold duration as a TDateTime value. You'd be much better off determining your preferred unit of measure and using Integer (perhaps Int64) or Double (if you need support for fractions of a unit). Then you can add or subtract, preferably using library routines, the duration from your start or end times.
The following code demonstrates some examples.
var
LStartTime, LEndTime: TDateTime;
LDuration_Mins: Integer;
begin
{ Init sample values for each calculation }
LStartTime := EncodeDateTime(2018, 3, 9, 8, 40, 0, 0);
LEndTime := EncodeDateTime(2018, 3, 9, 9, 0, 0, 0);
LDuration_Mins := 20;
{ Output result of each calculation }
Writeln(Format('Whole Duration: %d', [MinutesBetween(LStartTime, LEndTime)]));
Writeln(Format('Frac Duration: %.6f', [MinuteSpan(LStartTime, LEndTime)]));
Writeln(Format('Start Time: %s', [FormatDateTime('yyyy-mm-dd hh:nn:ss', IncMinute(LEndTime, -LDuration_Mins))]));
Writeln(Format('End Time: %s', [FormatDateTime('yyyy-mm-dd hh:nn:ss', IncMinute(LStartTime, LDuration_Mins))]));
end;
Additional Considerations
You said you're dealing with vehicle travel times. If you're dealing with long-haul travel you might have some other things to think about.
Daylight saving: If a vehicle starts its journey shortly before DST changes and ends after, you need to take this into account when calculating a missing value. Perhaps easiest would be to convert date-time values to UTC for the calculation. Which leads to...
Time zone changes: Again, unless your code is time-zone aware you're bound to make mistakes.
Compiler always appears to treat TDateTime as positive when doing numerical operations on it. Try this:
uses
System.SysUtils, System.DateUtils;
function InvertDate(ADateTime: TDateTime): TDateTime;
var
LMsec: Int64;
begin
LMsec := MillisecondsBetween(ADateTime, 0); //Always Positive
if ADateTime > 0 then
LMsec := 0 - LMsec;
Result := IncMillisecond(0, LMsec);
end;
var
LDate1: TDateTime;
LDate1Negative: TDateTime;
LDate2: TDateTime;
begin
try
LDate1 := IncMinute(0, 20);
LDate2 := IncMinute(0, -20);
WriteLn('Date1: ' + DateTimeToStr(LDate1));
// Output = Date1: 30/12/1899 00:20:00 [OK]
WriteLn('Date2: ' + DateTimeToStr(LDate2));
// Output = Date2: 29/12/1899 23:40:00 [OK]
WriteLn('-----');
WriteLn('Date1: ' + DateTimeToStr( InvertDate(LDate1) ));
// Output = Date1: Expected 29/12/1899 23:40:00
WriteLn('Date2: ' + DateTimeToStr( InvertDate(LDate2) ));
// Output = Date2: 30/12/1899 00:20:00
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
These lines give the date and time in UTC:
t:timedate(absolute_real_time() - (10*3600));
t0:substring(t,1,20);
t1:concat(substring(t,12,17), " ", substring(t,9,11), "/", substring(t,6,8), "/", substring(t,1,5));
t2:concat(substring(t,1,5), substring(t,6,8), substring(t,9,11), substring(t,12,14), substring(t,15,17), substring(t,18,20));
I know that '?\*autoconf\-version\*;' can give the Maxima version number, so maybe there is some undocumented way to get the local time.
Otherwise are there any ready-made functions that can convert
UTC time to local time given conditions for start/end of daylight saving time
e.g. UTC time to UK time (which is GMT/BST depending on the time of year)?
It's not clear to me exactly what you need, but perhaps the following helps. By the way, do you really need to extract the parts (year, month, day, etc)? If so, it might be more convenient to work directly in Lisp. See DECODE-UNIVERSAL-TIME at the Common Lisp Hyperspec (a web search will find it).
The timedate now (in the just-released Maxima 5.39) accepts an optional argument which is the time zone offset, in hours (plus or minus). The time zone offset may be noninteger (e.g. 2.5). Offset 0 indicates UTC. If the offset is omitted, the time is formatted in the local time zone.
(%i5) t:absolute_real_time();
(%o5) 3691202499
(%i6) timedate (t, 0);
(%o6) 2016-12-20 06:01:39+00:00
(%i7) timedate (t);
(%o7) 2016-12-19 22:01:39-08:00
Note that the daylight saving time flag is applied at the "time of the time". Here is a time from next summer, when daylight saving time is in effect.
(%i8) timedate (t + 6*30.25*24*3600);
(%o8) 2017-06-19 11:01:39-07:00
The parse_timedate function has also been (in Maxima 5.39) updated to recognize time zone offsets.
(%i9) parse_timedate ("2016-12-19 22:01:39-08:00");
(%o9) 3691202499
As with timedate if the offset is omitted, it is assumed to be in the local time zone.
(%i10) parse_timedate ("2016-12-19 22:01:39");
(%o10) 3691202499
Note also that Maxima does not recognize any symbolic time zone indicators such as "UTC", "GMT", "EDT", "America/New_York", etc., only numerical time zone offsets.
To clarify the problem, before revealing the solution:
these are the steps that I take in Maxima v5.30
to get the time in UTC, in a readable format:
Note: When I use Maxima v5.30 (in the UK),
for some unknown reason, the time is always UTC adjusted
by 10 hours, and does not adjust for DST.
/* 1st Jan 2017 12 noon: */
timedate(3692260800); /* "2017-01-01 22:00:00+10:00" */
timedate(3692260800-10*3600); /* "2017-01-01 12:00:00+10:00" */
substring(timedate(3692260800-10*3600),1,20); /* "2017-01-01 12:00:00" */
Note: timedate works better/differently in later versions of Maxima,
but some institutions recommend installing a specific version of Maxima.
Sometimes I want the date in the form: 'yyyyMMddHHmmss'.
A function for this is:
SecUTCToDate(vSec,vHour):=
block([d1,d2],
d1:timedate(vSec+vHour*3600),
d2:concat(substring(d1,1,5), substring(d1,6,8), substring(d1,9,11), substring(d1,12,14), substring(d1,15,17), substring(d1,18,20)),
parse_string(d2)
);
Note: [d1,d2] keeps those variables local to within the block, and not global.
To get the local time I have to add on hours based on my time zone (0 in the UK), and DST.
To calculate whether a time is within the DST period requires an individual function per time zone: in the UK, and many European countries, one such function is:
/* correct for the years 1900-2200 inclusive */
SecUTCIsDSTUK(vSec):=
block([vLeap,vDaysMar25,vDaysOct25,vWDayMar25,vWDayOct25,vRange1,vRange2],
vYear : parse_string(substring(timedate(vSec),1,5)),
vLeap : floor((vYear-1900)/4), if (vYear>=2100) then vLeap : vLeap-1,
vDaysMar25 : (vYear-1900)*365 + vLeap + 83,
vDaysOct25 : vDaysMar25 + 214,
vWDayMar25 : mod(vDaysMar25+1,7),
vWDayOct25 : mod(vDaysOct25+1,7),
vRange1 : (vDaysMar25+mod(-vWDayMar25,7))*86400 + 3600,
vRange2 : (vDaysOct25+mod(-vWDayOct25,7))*86400 + 3600,
if ((vSec >= vRange1) and (vSec < vRange2)) then 1 else 0);
You can create a mac file with such a function, and call up the the function when needed, e.g.:
load("C:\\MyFolder\\MyFile.mac");
SecUTCIsDSTUK(absolute_real_time());
SecUTCIsDSTUK(absolute_real_time()+86400*180);
thank you for your helpful response,
results (v. 5.39.0) (works fine, param 2 omitted gives local time, param 2 as 0 gives UTC):
t:3691202499;
timedate (t);
timedate (t + 6*30.25*24*3600);
timedate (t + 6*30*24*3600);
timedate (t, 0);
timedate (t + 6*30.25*24*3600, 0);
timedate (t + 6*30*24*3600, 0);
:lisp (decode-universal-time 3691202499)
:lisp (decode-universal-time 3691202499 0)
:lisp (decode-universal-time 3706754499)
:lisp (decode-universal-time 3706754499 0)
3691202499
"2016-12-20 06:01:39+00:00"
"2017-06-19 19:01:39+01:00"
"2017-06-18 07:01:39+01:00"
"2016-12-20 06:01:39+00:00"
"2017-06-19 18:01:39+00:00"
"2017-06-18 06:01:39+00:00"
39 1 6 20 12 2016 1 NIL 0
39 1 6 20 12 2016 1 NIL 0
39 1 7 18 6 2017 6 T 0
39 1 6 18 6 2017 6 NIL 0
results (v. 5.30.0) (it seems param 2 omitted gives UTC+10, with no daylight saving time):
(if this is true, I would have to find another way to get local time, possibly by Common LISP commands)
t:3691202499;
timedate (t);
timedate (t + 6*30.25*24*3600);
timedate (t + 6*30*24*3600);
:lisp (decode-universal-time 3691202499)
:lisp (decode-universal-time 3691202499 0)
:lisp (decode-universal-time 3706754499)
:lisp (decode-universal-time 3706754499 0)
3691202499
"2016-12-20 16:01:39+10:00"
"2017-06-20 04:01:39.0+10:00"
"2017-06-18 16:01:39+10:00"
39 1 16 20 12 2016 1 NIL -10
39 1 6 20 12 2016 1 NIL 0
39 1 16 18 6 2017 6 NIL -10
39 1 6 18 6 2017 6 NIL 0
(I can see that the timedate and decode-universal-time functions
have key differences between Maxima versions)
thank you for the website mention,
CLHS: Section The Environment Dictionary
http://clhs.lisp.se/Body/c_enviro.htm
is there a list of LISP commands that work in Maxima?
the main reason for the datestamp concerns:
to produce datestamps for filenames such as 'z title yyyymmddhhmmss.txt',
or for friendly dates inside those files such as 'hh:mm dd/mm/yyyy',
the string manipulation method was the simplest method
that I could successfully code (I don't explicitly need to extract individual d m y etc)