How to get the seconds and millisecond component from UTCTime? - datetime

In other words, I'm looking for the equivalent of Python's datetime.utcnow().
I'm also fine with a n-tuple containing years, months and so on, up until milliseconds (or microseconds).
I had thought of using show and then parsing the String value, but I believe there's something more convenient.

Re-parsing a string is very un-Haskellish, you certainly don't want that.
I'd use, from Data.Time.LocalTime,
todSec . localTimeOfDay . utcToLocalTime utc :: UTCTime -> Data.Fixed.Pico
that gives you seconds in picosecond-resolution.

Seconds and milliseconds since when? Presumably there is an epoch (time zero) hiding somewhere here. You subtract the epoch from the UTCTime to get a NominalDiffTime, and then extract the seconds and milliseconds from that.
secondsSince :: UTCTime -> UTCTime -> (Integer, Int)
secondsSince t0 t1 = (i, round $ d * 1000)
where (i, d) = properFraction $ diffUTCTime t1 t0
Of course you probably want t0 to be 1/1/1970 (the Unix epoch), in which case you import Data.Time.Clock.POSIX and use utcTimeToPOSIXSeconds, which returns a NominalDiffTime.
NominalDiffTime is an instance of (amongst other things) Fractional and Num, so you have access to all the usual numeric operators when manipulating them. From an arithmetical point of view (including conversions) it is treated as a number of seconds.
When using this, do bear in mind that Unix gets time fundamentally wrong because it doesn't have any room for leap seconds. Every few years there is a day with 86401 seconds instead of the usual 86400. Back in the 70s the idea of a computer needing to know about this would have seemed absurd (clocks were generally set by the sysadmin consulting his mechanical watch), so the Unix time_t simply counts seconds since the epoch and assumes that every day has exactly 86400 seconds. NominalDiffTime is "nominal" because it makes the same assumption.
The Right Thing would have been to make time_t a struct with a day number and seconds since midnight as separate fields, and have the time arithmetic functions consult a table of leap seconds. However that would have its own set of disadvantages because new leap seconds get designated every so often, so a program could give different results when run at different times. Or to put it in Haskell terms, "diffUTCTime" would have to return a result in the IO monad.

Related

Is it possible to encode date AND time (with some caveats) into 12 bits?

I have at my disposal 16 bits. Of them, 4 bits are the header and cannot be touched. This leaves us with 12 bits. I would like to encode date and time data into them. These are essentially logs being sent over LPWAN.
Obviously, it's impossible to encode proper generic date and time into it. Since the unix timestamp uses 32 bits, and projects like Compact Time Format use 5 bytes.
Let's say we don't really need the year, because this information is available elsewhere. Let's also say the time resolution of seconds doesn't have to be super accurate, so we can split the seconds into 30 second intervals. If we were to simply encode the data as is then:
4 bits month (0-11)
5 bits day (0-31)
5 bits hour (0-23)
6 bits minute (0-59)
1 bit second (0,30)
-----------------------------
21 bits
21 bits is much better than 32. But it's still not 12. I could subtract one bit from the minutes (rounding to the nearest even minute), and remove the seconds but that still leaves us with 19 bits. Which is still far from 12.
Just wondering if it's possible, and if anyone has any ideas.
12 bits can hold 2^12 = 4096 values, which feels pretty tight for a task. Not sure much can be done in terms of compressing a date time into a 4096 number. It is too little space to represent this data.
There are some workarounds, none of them able to achieve what you want, but maybe something you could use anyway:
Split date and time. Alternate with some algorithm between sending date/time, one bit can be used to indicate what data is being sent. This leaves 11 bits to encode either date or time. You could go a bit further and split time like this as well. Receiving side can then reconstruct a full date time having access to the previously received data.
You could have a schema where one date packet is sent as a starting point, and subsequent packets are incremented in N-second intervals from the start of the epoch
Remove date time from data completely, saving 12 bits, but send it periodically as a stand-alone heartbeat/datetime packet.
You could try compressing the whole data packet which could allow using more bits to represent date time and still fit into a smaller overall packet size
If data is sent at reasonable fixed intervals, you could use a circular counter of an interval of N seconds, this may work if you have few devices and you can keep track of when they start transmitting. For example a satellite was launched on XYZ date time, it send counter every 30 seconds, we received counter value of 100, to calculate date we use simple math XYZ + 30*100 seconds
No. Unless you'd be happy with representing less than a span of a day and a half. You can just count 4096 30-second intervals, and find that that will cover 34 hours and eight minutes. 4096 two-minute intervals is just four times that, or five days, 16 hours, and 32 minutes. Still a small fraction of a year.
If you can assure that the difference between successive log entries is small, then you can stuff that in 12 bits. You will need a special entry to give an initial date, and maybe you could insert such an entry when the difference betweem successive entries is too large.
#oleksii has some other good suggestions as well.

Getting date from the world time in millis

Is any math can sort out date from time-milli? (eg:1544901911)
It is possible to get time by a initial modulus of 86400 and dividing 3600 (hour) and modulus by 3600 and dividing by 60 (minute) of overal milli.
Is it possible to get date from these, I really don't know how it works (just knows that it begined from 1970 Jan 1 onwards).
Not using any code language, I am just asking the mathematics behind this.
I have problems making sense of what you wrote. 86400 is the number of seconds in a day. So if you have the time in seconds, and want the time of the day, then modulo 86400 makes sense. As your question starts with time in milliseconds, modulo 86400000 would be more appropriate. But I guess we get the idea either way.
So as I said, extracting the time of the day works as you know the number of seconds in a day. The number of seconds in a year is harder, as you have to deal with leap days. You can have a look at existing standard library implementations, e.g. Python datetime. That starts by taking the time (or rather number of days, i.e. time divided by time per day, whatever the unit) modulo 400 years, since the number of whole days in 400 years is fixed. Then it goes on looking at 100 year cycles, 4 year cycles and years, with case distinctions for leap years, and tables containing information about month lengths, and so on. Yes, this can be done, but it's tedious plus already part of standard libraries for most languages.

Why use ISO 8601 format for datetime in API instead of numeric milliseconds? [duplicate]

For passing times in JSON to/from a web API, why would I choose to use an ISO8601 string instead of simply the UTC epoch value? For example, both of these are the same:
Epoch = 1511324473
iso8601 = 2017-11-22T04:21:13Z
The epoch value is obviously shorter in length, which is always good for mobile data usage, and it's pretty simple to convert between epoch values and the language's local Date type variable.
I'm just not seeing the benefit to using an ISO string value.
Both are unambiguous and easy to parse in programs. The benefit of epoch like you have mentioned is that it is smaller and will be faster to process in your program. The downside is it means nothing to humans.
iso8901 dates are easy to read on their own and don't require the user to translate a number in to a recognizable date. The size increase in iso8601 is unnoticeable when compared to much much larger things like images.
Personally I would pick ease of reading over speed for an API as it will cut down on debugging time while inspecting values sent and received. In another situation such as passing times around internally you may wish to choose the speed of an integer over text so it depends which you think will be more useful.
Unix/Epoch Time
+ Compact
+ Easy to do arithmetic actions without any libraries, i.e. var tomorrow=now()+60*60*24
- Not human-readable
- Cannot represent dates before 1 January 1970
- Cannot represent dates after 19 January 2038 (if using Int32)
- Timezone and offset are "external" info, there is ambiguity if the value is UTC or any other offset.
- Officially the spec supports only seconds.
- When someone changes the value to milliseconds for better resolution, there is an ambiguity if the value is seconds or milliseconds.
- Older than ISO 8601 format
- Represents seconds since 1970 (as opposed to instant in time)
- Precision of seconds
ISO 8601 Time
+ Human readable
+ Represents instant in time, as opposed to seconds since 1970
+ Newer then Unix time format
+ Specifies representation of date, time, date-time, duration and interval!
+ Supports an offset representation
+ Precision of nanoseconds
- Less compact
- For any arithmetic actions, reach library is required (like java.time.OffsetDatetime)

ISO 8601 Repeating Intervals without Date

With ISO8601, is there a way to specify a repeating interval which starts at a given time for any day, and repeats over time in that day?
For example, does the following hold:
R2/T09:00:00Z/PT1H = R/2000-01-01T09:00:00/P1D + R/2000-01-01T10:00:00/P1D?
Or is the former not correct under the standard?
The motivation behind this is to run a task at 9am and 10am every day.
No, Iso 8601 cannot irregular repetitions. You would need evaluate/run both of those expressions.
Cron expressions would be a better option as it is widely supported, especially for running tasks. You can find cron expression builders on the web and a library for every language (and OS support with crontab in Unix systems). This expression would handle your use case 0 0 9,10 ? * * * and would run at 9 and 10 am of every day of every year.
Sorry for the response 2 years later.

why is 0-61 unit of second in POSIXct

when you search Date-Time Classes in R manual ,you can get
sec
0–61: seconds
why the seconds is not between 0-59 ?
As I recall this is for leap second adjustments.
Checking NEWS.* real quick I find eg
o .leap.seconds and the internal adjustment code now know about
the 23rd leap second on 2005-12-31: the internal code uses a
run-time test to see if the OS does.

Resources