64-bit CFCalendarComposeAbsoluteTime generated unexpected value - ios

I used below codes to generate absolute time in a 64-bit app:
CFTimeZoneRef cftz = CFTimeZoneCopyDefault();
CFCalendarRef cfgd = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar);
CFCalendarSetTimeZone(cfgd, cftz);
CFAbsoluteTime at = 0.0;
CFCalendarComposeAbsoluteTime(cfgd,
&at,
"yMdHms",
year,
month,
day,
hour,
minute,
second);
Where year, month, day, hour, minute and second were:
2005, 4, 18, 12, 0, 0.0
But the generated absolute time was not as expected. It turned to 2005-04-19 13:17:27 PDT.
And it would go too far wrong if I added more control, for example, locale.
Any one suffered the same issue before? or know anything about this API?

Related

Parse time string to hours, minutes and seconds in Lua

I am currently working on a plugin for grandMA2 lighting control using Lua. I need the current time. The only way to get the current time is the following function:
gma.show.getvar('TIME')
which always returns the current system time, which I then store in a variable. An example return value is "12h54m47.517s".
How can I separate the hours, minutes and seconds into 3 variables?
If os.date is available (and matches gma.show.getvar('TIME')), this is trivial:
If format starts with '!', then the date is formatted in Coordinated Universal Time. After this optional character, if format is the string "*t", then date returns a table with the following fields: year, month (1–12), day (1–31), hour (0–23), min (0–59), sec (0–61, due to leap seconds), wday (weekday, 1–7, Sunday is 1), yday (day of the year, 1–366), and isdst (daylight saving flag, a boolean). This last field may be absent if the information is not available.
local time = os.date('*t')
local hour, min, sec = time.hour, time.min, time.sec
This does not provide you with a sub-second precision though.
Otherwise, parsing the time string is a typical task for tostring and string.match:
local hour, min, sec = gma.show.getvar('TIME'):match('^(%d+)h(%d+)m(%d*%.?%d*)s$')
-- This is usually not needed as Lua will just coerce strings to numbers
-- as soon as you start doing arithmetic on them;
-- it still is good practice to convert the variables to the proper type though
-- (and starts being relevant when you compare them, use them as table keys or call strict functions that check their argument types on them)
hour, min, sec = tonumber(hour), tonumber(min), tonumber(sec)
Pattern explanation:
^ and $ pattern anchors: Match the full string (and not just part of it), making the match fail if the string does not have the right format.
(%d)+h: Capture hours: One or more digits followed by a literal h
(%d)+m: Capture minutes: One or more digits followed by a literal m
(%d*%.?%d*)s: Capture seconds: Zero or more digits followed by an optional dot followed by again zero or more digits, finally ending with a literal s. I do not know the specifics of the format and whether something like .1s, 1.s or 1s is occasionally emitted, but Lua's tonumber supports all of these so there should be no issue. Note that this is slightly overly permissive: It will also match . (just a dot) and an s without any leading digits. You might want (%d+%.?%d+)s instead to force digits appearing before & after the dot.
Lets do it with string method gsub()
local ts = gma.show.getvar('TIME')
local hours = ts:gsub('h.*', '')
local mins = ts:gsub('.*%f[^h]', ''):gsub('%f[m].*', '')
local secs = ts:gsub('.*%f[^m]', ''):gsub('%f[s].*', '')
To make a Timestring i suggest string method format()
-- secs as float
timestring = ('[%s:%s:%.3f]'):format(hours, mins, secs)
-- secs not as float
timestring = ('[%s:%s:%.f]'):format(hours, mins, secs)

F# - convert time in microsecond to day of the week

I am trying to learn F# and was wondering if i have a json object which has time in microseconds as int. I want to get the day, date and time out of this and was wondering how to do it.
I actually happen to have needed to do this recently. You'll almost certainly want to use the .NET time objects (DateTime, DateTimeOffset, TimeSpan) in some capacity. Here's what I went with:
let TicksPerMicrosecond =
TimeSpan.TicksPerMillisecond / 1000L
let FromUnixTimeMicroseconds (us: int64) =
DateTimeOffset.FromUnixTimeMilliseconds 0L + TimeSpan.FromTicks(us * TicksPerMicrosecond)
From TimeSpan.TicksPerMillisecond we can calculate how many are in a microsecond (if I remember correctly it's 10, but this way it doesn't seem as "magic"). Then I can convert the microseconds value into ticks and add it to the epoch date.
To get the day of the week (assuming the time zone is UTC), you'd just use DateTimeOffset.DayOfWeek.

Find the start of a given week and year with Delphi

I'm looking for a Delphi (10+) function that returns a TDate with a given year and a week number:
function StartDate(2021, 53): TDate should return 2021-01-01.
While WeekOfTheYear(EncodeDate(2021,1,1)) returns 53 (correct), I can't do the other way round with StartOfAWeek(2021,53, 1) nor StartOfAWeek(2021,53, 5) (5=it's a friday) - it's not recognized as a valid date (=exception). Any suggestions?
Edited:
I'm looking for a ISO 8601 compliant function (like the internal Delphi routines), with Monday=1 and special week consideration (like 2021-01-01), or to be more precise: the "vice versa" routine of WeekOfTheYear
The function you need is:
StartOfAWeek(Year, Week, 1)
You observe that StartOfAWeek(2021, 53, 1) raises an exception. That is correct because 2021 does not have 53 weeks. It only has 52. Week 52 ends on the last day of 2021.
You are getting confused by the result of
WeekOfTheYear(EncodeDate(2021,1,1))
This returns 53, but because the date is at the start of the year, this is week 53 of 2020.

Unix time with NSDate reveals erroneous results

I live in Denmark (UTC + 1 ) and I am working with a webapi that sends my app a unix timestamp since 1970-1-1 00:00:00. The time is in the future (train depatures)
If I check the timestamp in Numbers or Excel it gives me the correct time
To calculate the number of minutes until the train departures I do like this:
let unixTimeTrainDeparture = 1419327780 //(or some time in the future)
let unixRightNow = NSDate().timeIntervalSince1970
let minutesToDeparture = (Int(unixTimeTrainDeparture) - Int(unixRightNow))/60
However this gives 60 minutes too much?
And If I do a
let dateTest = NSDate(string: "1970-01-01 00:00:00 +0000")!
will give me 1 jan 1970 :01:00:00 +0000
This does not make sense to me. It is like the timeIntervalSince1970 gives me 3600 sec too less, as it starts from 1970-1-1 01:00 rather than 00:00? It this a bug or is it the way it should be?
I can correct the time by using the
let tz = NSTimeZone.defaultTimeZone()
let seconds = tz.secondsFromGMTForDate(NSDate())
and then subtracting the seconds from my result. However, what happens when we move into summer time?
timeIntervalSince1970 always gives the time in GMT. Your unixTimeTrainDeparture is probably the time in GMT+1, which explains the 60 minute difference (or 120 minutes in summer time). Same goes with the string conversion - you input a GMT time and it outputs the date in whatever timezone you have configured (I'm guessing your computer's setting is GMT+1 as well).
When working with timezones, always start with GMT/UTC and don't do any timezone conversions until displaying the date to the user.
Do you have any control over the web API? If so - configure it to send GMT instead. This should completely avoid time zone and daylight savings issues.
If you cannot do that you will have to implement some function to convert the timestamp yourself, accounting for the possibility that a future timestamp could be in a different timezone (eg daylight savings). NSTimeZone might be very useful for this!
Hope I have understood your problem correctly!
Edit, added example that should handle DST:
// Date far in the future in DST, replace this
let unixTimeTrainDeparture = NSDate(timeIntervalSince1970: 1436447418)
let now = NSDate()
// Assume unixTimeTrainDeparture is in the Copenhagen timezone
let tz = NSTimeZone(name: "Europe/Copenhagen")
// This is 3600 in non-DST, otherwise 7200
let offset = tz!.secondsFromGMTForDate(unixTimeTrainDeparture)
let realUnixTimeTrainDeparture = Int(unixTimeTrainDeparture.timeIntervalSince1970) - offset
let timeToDeparture = realUnixTimeTrainDeparture - Int(now.timeIntervalSince1970)

Operations on DateTime in rails

Is it possible to subtract one DateTime from another and get the result in Time.
Example if we subtract 2011-08-27 01:00:00 UTC from 2011-08-29 08:13:00 UTC, the result should be 55:13:00 (hope I didn't make a mistake while calulating :p)
Thanks.
Time is generally expressed in seconds when doing math like this, even fractional seconds if you want. A Time represents a specific point in time, which while internally represented as seconds since the January 1, 1970 epoch, is not intended to be a scalar unit like that.
If you have two DateTime objects, you can determine the difference between them like this:
diff = DateTime.parse('2011-08-29 08:13:00 UTC').to_time - DateTime.parse('2011-08-27 01:00:00 UTC').to_time
# => 198780.0
Once you have the number of seconds, the rest is simply a formatting problem:
'%d:%02d:%02d' % [ diff / 3600, (diff / 60) % 60, diff % 60 ]
# => "55:13:00"

Resources