I was working on a project and wanted to add the difference in DateTime in terms of minutes, hours, days, weeks, months and years. I was able to get in minutes up to days. e.g.
DateTime.now().difference(DateTime(2019, 10, 7)).inDays
But I had a hard time creating it for weeks, months and years. How can I do so, please help
I constructed a package to help me with this called Jiffy
Jiffy([2018, 1, 29]).diff(Jiffy([2019, 10, 7]), Units.DAY); // -616
Jiffy([2018, 1, 29]).diff(Jiffy([2019, 10, 7]), Units.WEEK); // -88
Jiffy([2018, 1, 29]).diff(Jiffy([2019, 10, 7]), Units.MONTH; // -20
Jiffy([2018, 1, 29]).diff(Jiffy([2019, 10, 7]), Units.YEAR); // -1
you can calculate month diff size manually (without use any packege):
static int getMonthSizeBetweenDates(DateTime initialDate, DateTime endDate){
return calculateMonthSize(endDate)-calculateMonthSize(initialDate)+1;
}
static int calculateMonthSize(DateTime dateTime){
return dateTime.year*12+dateTime.month;
}
getMonthSizeBetweenDates method gives you how many months between your initial and end dates.
for example : your initial date is 1.1.2022 and your end date is 1.3.2022 .
then this method return 3 (january, fabruary and march)
You can find week and year diff bye using this logic.
Another method:
static int getMonthSizeBetweenDates2(DateTime initialDate, DateTime endDate){
return (endDate.year-initialDate.year)*12+(endDate.month-initialDate.month)+1;
}
There is a very simple and easy way to do this, and requires very little date/time arithmetic knowledge.
Simply compare both DateTimes' microsecondSinceEpoch values:
Duration compare(DateTime x, DateTime y) {
return Duration(microseconds: (x.microsecondsSinceEpoch - y.microsecondsSinceEpoch).abs())
}
DateTime x = DateTime.now()
DateTime y = DateTime(1994, 11, 1, 6, 55, 34);
Duration diff = compare(x,y);
print(diff.inDays);
print(diff.inHours);
print(diff.inMinutes);
print(diff.inSeconds);
The code above works, and works much more efficiently than conducting checks for leap-years and aberrational time-based anomalies.
To get larger units, we can just approximate. Most end-users are satisfied with a general approximation of this sort:
Weeks: divide days by 7 and round.
Months: divide days by 30.44 and round; if < 1, display months instead.
Years: divide days by 365.25 and floor, and also display months modulo 12.
Related
I want to convert an Int64 representing the number of microseconds passed since 12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001, in the Gregorian calendar) into a Julia datetime.
julia> time = Dates.Microsecond(6369175082331949400)
julia> Dates.format(time, "yyyymmdd HH:MM:SS.sss")
If you need a DateTime, just make sure you have your Int64 correctly in milliseconds, and you can use the (undocumented) UTInstant constructor, and then later add back the fractional microseconds (comment: your example number, 6369175082331949400, seems big for recent Gregorian time in microseconds, it may be nanoseconds):
julia> using Dates
julia> t = now().instant
Dates.UTInstant{Millisecond}(63694318624788 milliseconds)
julia> dump(t)
Dates.UTInstant{Millisecond}
periods: Millisecond
value: Int64 63694318624788
julia> t2 = Dates.UTInstant(Millisecond(63691750823319))
Dates.UTInstant{Millisecond}(63691750823319 milliseconds)
julia> DateTime(t2)
2019-04-24T01:00:23.319
julia> t3 = DateTime(t2)+ Dates.Microsecond(494)
2019-04-24T01:00:23.319
You can get what you want using Dates.epochms2datetime and applying an adjustment to it for your case as shown below.
Lets take datetime_value as the date we are interested in getting:
datetime_value = Dates.DateTime(2019,1,1,0,0,0)
date_start = Dates.DateTime(1,1,1,0,0,0)
date_diff = datetime_value - date_start
This gives you a value of 63681897600000 milliseconds for date_diff. Now Dates.epochms2datetime considers start of epoch as 0000-01-01T00:00:00. So we need to add 1 Year and 1 Day to the result after using Dates.epochms2datetime to arrive at our datetime value from the milliseconds value:
julia> Dates.epochms2datetime(63681897600000) + Dates.Year(1) + Dates.Day(1)
2019-01-01T00:00:00
I'm not sure I completely understand the question, as Dates.Microsecond merely returns the Int64 value of a Date or Time. However, you can create the DateTime value from a specific date and then work from there. Subtraction is allowed for DateTime values and it returns the difference in milliseconds.
using Dates
dateThen = DateTime(1, 1, 1, 0, 0, 0)
dateNow = now(UTC)
diff = dateNow - dateThen
dump(diff * 1000)
Int64 63694261047549000 (or whatever time you run it.)
Using some of the ideas provided, I came up with:
function convert_datetime(time)::DateTime
num = div(time, 100000)
remainder = rem(time, 100000)
time = DateTime(Dates.UTInstant(Millisecond(num))) + Dates.Day(1)
# time = Dates.epochms2datetime(trade.date_time/100000) + Dates.Year(1) + Dates.Day(1)
time + Dates.Microsecond(remainder)
end
I'd like to add a certain period of time to an existing DateTime value (in {{Y,M,D},{H,m,s}} format), but don't see a function (such as in the Calendar module) that allows me to manipulate a DateTime value directly.
How can I add (for example) 10 seconds, 10 minutes, or 10 hours to such a value?
You can use the Calendar module to convert the DateTime to seconds, which makes it easier to add the desired seconds, minutes, hours, etc.
For example, to add 10 seconds:
Date = {{2018,8,14},{13,10,25}}.
DateInSeconds = calendar:datetime_to_gregorian_seconds(Date). % 63701471425
NewDateInSeconds = DateInSeconds + 10. % 63701471435
calendar:gregorian_seconds_to_datetime(NewDateInSeconds). % {{2018,8,14},{13,10,35}}
For 10 minutes or 10 hours, just perform a little math:
Date = {{2018,8,14},{13,10,25}}.
DateInSeconds = calendar:datetime_to_gregorian_seconds(Date). % 63701471425
NewDateInSeconds = DateInSeconds + (10 * 60 * 60). % 63701507425 (10 hours)
calendar:gregorian_seconds_to_datetime(NewDateInSeconds). % {{2018,8,14},{23,10,25}}
To make life easier, you could even create a function for this, to add additional time to (or subtract time from) an existing DateTime:
-type datetime() :: {{non_neg_integer(), pos_integer(), pos_integer()},
{non_neg_integer(), non_neg_integer(), non_neg_integer()}}.
-type timespan() :: {integer(), integer(), integer()}.
-spec add_time_to_datetime(datetime(), timespan()) -> datetime().
add_time_to_datetime(Date, {Hour, Min, Sec}) ->
DateInSeconds = calendar:datetime_to_gregorian_seconds(Date),
NewDateInSeconds = DateInSeconds + (Hour * 60 * 60) + (Min * 60) + Sec,
calendar:gregorian_seconds_to_datetime(NewDateInSeconds).
Also you can use special time managment libs such as qdate.
Example usage, adding a year, month and minute, and removing 3 days and 5 hours.
NewDate = qdate:add_date({{1, 2, -3}, {-5, 1, 0}}, {{2018, 8, 16}, {11, 0, 1}}).
If you want to accept two datetime structures and subtract the second from the first, conversion to Gregorian seconds, performing the subtraction, and then reconversion is the most common way:
sub_datetime(DT1, DT2) ->
Seconds1 = calendar:datetime_to_gregorian_seconds(DT1),
Seconds2 = calendar:datetime_to_gregorian_seconds(DT2),
Diff = Seconds1 - Seconds2,
calendar:gregorian_seconds_to_datetime(Diff).
Addition is the same thing, just with the opposite operation (and of course this becomes commutative as well).
add_datetime(DT1, DT2) ->
Seconds1 = calendar:datetime_to_gregorian_seconds(DT1),
Seconds2 = calendar:datetime_to_gregorian_seconds(DT2),
Sum = Seconds1 + Seconds2,
calendar:gregorian_seconds_to_datetime(Sum).
This works in all situations and doesn't require deciphering anything or math other than the single operation (on your behalf, anyway). You notice, of course, the opportunity here for pulling the one unique part of these two functions out -- but that sort of DRY isn't really called for with just two functions. Meh.
If you want a "list-of-args friendly" sort of way to call the above:
add_time(Years, Months, Days, Hours, Minutes, Seconds, Target) ->
AddedTime = {{Years, Months, Days}, {Hours, Minutes, Seconds}},
add_datetime(AddedTime, Target).
I'm trying to create simple function just to change time zone of a time to another (Lets assume UTC to +0700 WIB). Here is the source code. I have 2 functions, first GenerateWIB which will change just your time zone into +0700 WIB with same datetime. Second is GenerateUTC which will change given time's timezone into UTC. GenerateUTC works perfectly while another is not.
expect := time.Date(2016, 12, 12, 1, 2, 3, 4, wib)
t1 := time.Date(2016, 12, 12, 1, 2, 3, 4, time.UTC)
res := GenerateWIB(t1)
if res != expect {
fmt.Printf("WIB Expect %+v, but get %+v", expect, res)
}
The res != expect always fullfilled with this result.
WIB Expect 2016-12-12 01:02:03.000000004 +0700 WIB, but get 2016-12-12 01:02:03.000000004 +0700 WIB
But it is the same time right? Did i miss something?
There is an .Equal() method to compare dates :
if !res.Equal(expect) {
...
Quoting the doc :
Note that the Go == operator compares not just the time instant but also the Location and the monotonic clock reading. Therefore, Time values should not be used as map or database keys without first guaranteeing that the identical Location has been set for all values, which can be achieved through use of the UTC or Local method, and that the monotonic clock reading has been stripped by setting t = t.Round(0). In general, prefer t.Equal(u) to t == u, since t.Equal uses the most accurate comparison available and correctly handles the case when only one of its arguments has a monotonic clock reading.
If you look at the code for the time.Time(*) struct, you can see that this struct has three private fields :
type Time struct {
...
wall uint64
ext int64
...
loc *Location
}
and the comments about those fields clearly indicate that, depending on how the Time struct was built, two Time describing the same point in time may have different values for these fields.
Running res == expect compares the values of these inner fields,
running res.Equal(expect) tries to do the thing you expect.
(*) time/time.go source code on master branch as of oct 27th, 2020
Dates in golang must be compared with Equal method. Method Date returns Time type.
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
and Time type have Equal method.
func (t Time) Equal(u Time) bool
Equal reports whether t and u represent the same time instant. Two times can be equal even if they are in different locations. For example, 6:00 +0200 CEST and 4:00 UTC are Equal. See the documentation on the Time type for the pitfalls of using == with Time values; most code should use Equal instead.
Example
package main
import (
"fmt"
"time"
)
func main() {
secondsEastOfUTC := int((8 * time.Hour).Seconds())
beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)
// Unlike the equal operator, Equal is aware that d1 and d2 are the
// same instant but in different time zones.
d1 := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
d2 := time.Date(2000, 2, 1, 20, 30, 0, 0, beijing)
datesEqualUsingEqualOperator := d1 == d2
datesEqualUsingFunction := d1.Equal(d2)
fmt.Printf("datesEqualUsingEqualOperator = %v\n", datesEqualUsingEqualOperator)
fmt.Printf("datesEqualUsingFunction = %v\n", datesEqualUsingFunction)
}
datesEqualUsingEqualOperator = false
datesEqualUsingFunction = true
resources
Time type documentation
Equal method documentation
time.Date
LinkedIn's API returns the following value:
[creationTimestamp] => 1407247548000
It looks similar to a UNIX timestamp, but there are three "extra" zeros at the end. What format is this in, and how can I decode it?
It is a timestamp in milliseconds. Handling this is language dependent. Some languages may expect a timestamp in milliseconds, while others may expect it in seconds. Python 3, for example, expects seconds, but also handles microseconds (1000 milliseconds).
from datetime import datetime
ts = 1407247548124
dt = datetime.utcfromtimestamp(ts / 1000)
print(dt) # datetime(2014, 8, 5, 14, 5, 48, 124000)
Python 2 doesn't handle milliseconds directly (it ignores the fractional part), so you need to split the milliseconds out separately.
from datetime import datetime
ts = 14072475481234
secs, millis = divmod(ts, 1000)
dt = datetime.utcfromtimestamp(secs).replace(microsecond=millis * 1000)
print(dt) # datetime(2014, 8, 5, 14, 5, 48, 124000)
I am trying to figure out how to best calculate work experience using momentjs.
Let's say I have had the following jobs:
from december 15. 2013 - march 15 2013
from february 20. 2013 - june 1. 2013
from september 1 2013 - december 1 2013.
as you can see there is an overlap between job 1 and 2, and there is a gap between job 2 and 3.
The challenge is that i just can't calculate the difference between the start of job 1 and the end of job 3, since there is a gap between job 2 and job 3.
On the other hand I cannot just add the timediff for each job since there is an overlap between job 1 and job 2.
Any input on how to tackle this the best, is appreciated.
thanks,
Thomas
This problem is unfortunately not solvable with moment.js. But I wrote a simple solution for you, using integers as start end end values:
calc_duration = function(list) {
// calculate the duration and add it to the list elements
// when you are working with you need to adjust how x.duration
// is retrieved
list_with_duration = list.map( function(x){
x.duration = x.end - x.start
return x
}).sort( function(a,b){
return a.start > b.start
});
// sums all the durations together except for overlapping dates, there it
// will only add the time span of the second date that exclusive of the
// first date
total_duration = list_with_duration.reduce( function(sum, curr, i, list){
if (i == 0 || list[i-1].end < curr.start ) {
return sum + curr.duration;
} else if ( list[i-1].end > curr.end ) {
return sum;
} else {
return sum + curr.end - list[i-1].end;
}
}, 0);
return total_duration;
}
calc_duration([{start: 0, end: 10},{start: 5, end: 15},{start:20, end: 30}])
//returns 25
calc_duration([{start: 20, end: 30},{start: 5, end: 50},{start:0, end: 10}])
//returns 50