Difference between 2 DateTime in hours in Elixir - datetime

My goal is to find a difference in hours between now and some provided date_time. I'm trying to do this this way:
pry(1)> dt1
#DateTime<2017-10-24 05:12:46.000000Z>
pry(2)> Ecto.DateTime.to_erl(dt1)
** (FunctionClauseError) no function clause matching in Ecto.DateTime.to_erl/1
The following arguments were given to Ecto.DateTime.to_erl/1:
# 1
#DateTime<2017-10-24 05:12:46.000000Z>
Attempted function clauses (showing 1 out of 1):
def to_erl(%Ecto.DateTime{year: year, month: month, day: day, hour: hour, min: min, sec: sec})
(ecto) lib/ecto/date_time.ex:608: Ecto.DateTime.to_erl/1
# ............
How to fix that? Or is there a better way to achieve my goal?
Note that I don't use timex and won't use it, neither any third-party library. Only ones built-in in Elixir/Erlang/Phoenix.

You can use DateTime.diff/3:
iex> dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...> hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...> utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> dt2 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...> hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...> utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.diff(dt1, dt2)
18000
iex> DateTime.diff(dt2, dt1)
-18000
Since DateTime.diff/3 returns seconds you have to calculate the hours out of the result like this:
result_in_hours = result_in_seconds/(60*60)

This answer has been added before topic author edited his question and excluded external libs from the scope. However, I'm not deleting it as I find Timex extremely useful and maybe someone will be interested in using it as well (I have nothing to do with Timex creators)
I strongly recommend using Timex library. It's perfect for date/time calculations with different formats and time zones.
So in your case to easily calculate hour difference you just need to:
Timex.diff(dt1, DateTime.utc_now, :hours)
You can find diff/3 docs here.

Ignoring timezones entirely here (to do that it is easiest to convert everything to UTC, then cast to whatever is local), the pure Erlang way is to do something along these lines.
1> Event = {{2017,05,23},{13,11,23}}.
{{2017,5,23},{13,11,23}}
2> Now = calendar:local_time().
{{2017,10,24},{14,44,1}}
3> EventGSec = calendar:datetime_to_gregorian_seconds(Event).
63662764283
4> NowGSec = calendar:datetime_to_gregorian_seconds(Now).
63676075441
5> Elapsed = NowGSec - EventGSec.
13311158
6> calendar:seconds_to_daystime(Elapsed).
{154,{1,32,38}}
The exact solution would depend, of course, on the resolution that you require. Extracting that into a function that returns a tuple of the form {Days, {Hours, Minutes, Seconds}} gives us:
-spec elapsed_time(calendar:datetime()) -> {Days, Time}
when Days :: non_neg_integer(),
Time :: calendar:time().
elapsed_time(Event) ->
Now = calendar:local_time(),
EventGSec = calendar:datetime_to_gregorian_seconds(Event),
NowGSec = calendar:datetime_to_gregorian_seconds(Now),
Elapsed = NowGSec - EventGSec,
calendar:seconds_to_daystime(Elapsed).
(Of course, the above could be composed on a single line -- but why would you ever do that?)
I'm sure there are some wazoo Elixir libraries that do things in a totally different way. Have fun with those. This answer only addresses the underlying native libraries. Most of the time functions in the Erlang standard library are now based on integer-based time units (seconds, milliseconds, or nanoseconds) instead of the older erlang:now() timestamp form (which is now deprecated). The exact way you should write your version of the function above depends on what kind of resolution you require and formatting of the original input (Unix-era nanoseconds are quite common for the type of timestamps I deal with myself, for example -- but are inapplicable to a datetime data type).
Remember: time calculations are tricky, subtle and hard to get right in edge cases. The standard libraries for most languages actually get quite a lot of TZ and time diff issues wrong -- and if that's OK for your case then just don't worry about it. In any case, I suggest at least skimming the Time and Time Correction in Erlang page of the standard docs -- even if it does not apply to your current situation, eventually you'll probably be in a situation where subtle timing issues will matter.

Related

How to get current time in milliseconds in Haxe?

I need a function that returns the local time in milliseconds on the CPP target.
I tried Haxe's Date class, but Date.now() gives me the time in seconds.
Sys.time() * 1000.0 - http://api.haxe.org/Sys.html#time
Gives the most precise timestamp value (in seconds)
To be clear, I tried this and got millisecond resolution on the cpp target. Sys is available on cpp, cs, java, macro, neko, php and python.
You could try Date.now().getTime(), however:
Returns the timestamp of the date. It might only have a per-second precision depending on the platforms.
A fast way of getting a timestamp would be to use the haxe.Timer.stamp() method.
Example:
import haxe.Timer;
var timestamp:Float = Timer.stamp(); // return a timestamp in seconds with fractions
Note that the value itself might differ depending on platforms, only differences between two values make sense.

Convert .NET timestamp

Anyone know what sort of timestamp this is?
130580051014610352
I believe it's ticks since 1970 or something, common in .NET.
I need to convert it to YYYYMMDDHH24MISS timestamp in AutoHotkey.
Appreciate any help
It would appear to be a Windows file time. Quoting MSDN:
A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC).
However, keep in mind that the file system where you obtained this timestamp is important.
NTFS properly stores file times based on the UTC time.
FAT16 and FAT32 store file times based on the local time.
This can be a problem if (for example) you save a file to a thumbdrive on one computer, then load it from another in a different time zone.
It can also be problematic within a single timezone because local times can't disambiguate between values that are in a daylight saving time fall-back transition period.
Assuming the value came from NTFS and is therefore UTC-based, you can get the UTC time in .NET code by using DateTime.FromFileTimeUtc, or you can get the equivalent local time by using DateTime.FromFileTime.
I'm not sure exactly what the equivalent code would be in AutoHotkey's scripting language, but I did notice that it already has a built-in function for getting a timestamp from a file, if that's what you're doing.
Someone posted a solution in AHK forums:
TicksToTime(FileTicks,UTC="")
{ ; 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC)
; FileTicks := 131817689607677716
FileSeconds := FileTicks // 10000000
DateTimeUTC := 1601
DateTimeUTC += FileSeconds, S
if (UTC = 1)
Return DateTimeUTC
; LocalTicks := FileTimeToLocalFileTime(FileTicks) ;;;
VarSetCapacity(FileTime, 8, 0)
VarSetCapacity(LocalTime, 8, 0)
NumPut(FileTicks, FileTime, "UInt64")
DllCall("FileTimeToLocalFileTime", "Ptr", &FileTime, "Ptr", &LocalTime)
FileSeconds := (NumGet(LocalTime, "UInt64") // 10000000)
DateTimeLoc := 1601
DateTimeLoc += FileSeconds, S
;utc time = DateTimeUTC
Return DateTimeLoc
}

Lua - Using os.date

I'm reading a date in a field, ex: 23/01/2015 11:04:06.265842 I would like to get 23/01/2015 11:04:06.26.
The purpose is to compare two datetime and get the result time, for example 2.16 seconds between the two times.
Actually I'm doing : fields["Date"]=os.date("%c", fields["frame.time_epoch"])
frame.time_epoch come from a .pcap file (wireshark)
EDIT:
You can't get millisecond precision with os.date - the maximum resolution it allows is second (see it here http://www.lua.org/pil/22.1.html)
You could try adding it yourself:
local epoch = fields["frame.time_epoch"]
local milliseconds = (epoch - math.floor(epoch))*1000
fields["Date"]=("%s.%03d"):format(os.date("%c", epoch), milliseconds)

How to get the current TimeStamp?

I'm trying to get the current time as TimeStamp without success.
I have this code:
QDateTime setTime = QDateTime::fromString (QString("1970-07-18T14:15:09"), Qt::ISODate);
QDateTime current = QDateTime::currentDateTime();
uint msecs = setTime.time().msecsTo(current.time());
return QString::number(msecs);
The output is
Sunday, January 25th 1970, 03:17:35 (GMT)
In Qt 4.7, there is the QDateTime::currentMSecsSinceEpoch() static function, which does exactly what you need, without any intermediary steps. Hence I'd recommend that for projects using Qt 4.7 or newer.
I think you are looking for this function:
http://doc.qt.io/qt-5/qdatetime.html#toTime_t
uint QDateTime::toTime_t () const
Returns the datetime as the number of seconds that have passed since 1970-01-01T00:00:00, > Coordinated Universal Time (Qt::UTC).
On systems that do not support time zones, this function will behave as if local time were Qt::UTC.
See also setTime_t().
Since Qt 5.8, we now have QDateTime::currentSecsSinceEpoch() to deliver the seconds directly, a.k.a. as real Unix timestamp. So, no need to divide the result by 1000 to get seconds anymore.
Credits: also posted as comment to this answer. However, I think it is easier to find if it is a separate answer.

Python 3: timestamp to datetime: where does this additional hour come from?

I'm using the following functions:
# The epoch used in the datetime API.
EPOCH = datetime.datetime.fromtimestamp(0)
def timedelta_to_seconds(delta):
seconds = (delta.microseconds * 1e6) + delta.seconds + (delta.days * 86400)
seconds = abs(seconds)
return seconds
def datetime_to_timestamp(date, epoch=EPOCH):
# Ensure we deal with `datetime`s.
date = datetime.datetime.fromordinal(date.toordinal())
epoch = datetime.datetime.fromordinal(epoch.toordinal())
timedelta = date - epoch
timestamp = timedelta_to_seconds(timedelta)
return timestamp
def timestamp_to_datetime(timestamp, epoch=EPOCH):
# Ensure we deal with a `datetime`.
epoch = datetime.datetime.fromordinal(epoch.toordinal())
epoch_difference = timedelta_to_seconds(epoch - EPOCH)
adjusted_timestamp = timestamp - epoch_difference
date = datetime.datetime.fromtimestamp(adjusted_timestamp)
return date
And using them with the passed code:
twenty = datetime.datetime(2010, 4, 4)
print(twenty)
print(datetime_to_timestamp(twenty))
print(timestamp_to_datetime(datetime_to_timestamp(twenty)))
And getting the following results:
2010-04-04 00:00:00
1270339200.0
2010-04-04 01:00:00
For some reason, I'm getting an additional hour added in the last call, despite my code having, as far as I can see, no flaws.
Where is this additional hour coming from?
# Ensure we deal with `datetime`s.
date = datetime.datetime.fromordinal(date.toordinal())
(That's chopping off the time-of-day completely, as ‘ordinal’ is only a day number. Is that what you meant to do? I suspect not.)
Anyway, as Michael said, datetime.fromtimestamp gives you a naïve datetime corresponding to what local time for that POSIX (UTC) timestamp would be for you. So when you call —
date = datetime.datetime.fromtimestamp(adjusted_timestamp)
you're getting the local time for the POSIX timestamp representing 2010-04-04T00:00:00, which of course in BST is an hour ahead. This doesn't happen in the return direction because your epoch is in January, when BST is not in force. (However your EPOCH would also be completely off if you weren't in the UK.)
You should replace both your uses of datetime.fromtimestamp with datetime.utcfromtimestamp.
It's sad that datetime continues the awful time tradition of keeping times in local time. Calling them ‘naïve’ and taking away the DST flag just makes them even worse. Personally I can't stand to use datetime, preferring integer UTC timestamps for everything (converting to local timezones for formatting only).
Judging by your profile, you're in the UK. That means you're currently running on UTC+1 due to DST.
If I take your timestamp and run it through datetime.fromtimestamp on Python 2.6 (I know you use Python 3, but this is what I have), that shows me that it believes it refers to 2010-04-04 02:00:00 - and I'm in CEST, so that's UTC+2.
Running datetime.fromtimestamp(0), I get that the epoch is 1970-01-01 01:00:00. This then shows me that it is correctly adding only a single hour (since January 1st is outside of DST, and the epoch is midnight UTC on that date, it would be 01:00 here).
In other words, your problem is that you're sending in a time which has DST applied, but datetime_to_timestamp treats it as if DST didn't exist. timestamp_to_datetime, however, applies the DST.
Unfortunately, I don't know enough Python to know how you would solve this, but this should at least give you something to go on.

Resources