Time Comparison

How to do date/time comparison

Use the time package to work with time information in Go.

Time instants can be compared using the Before, After, and Equal
methods. The Sub method subtracts two instants, producing a Duration.
The Add method adds a Time and a Duration, producing a Time.

Play example:

package main

import (
"fmt"
"time"
)

func inTimeSpan(start, end, check time.Time) bool {
return check.After(start) && check.Before(end)
}

func main() {
start, _ := time.Parse(time.RFC822, "01 Jan 15 10:00 UTC")
end, _ := time.Parse(time.RFC822, "01 Jan 16 10:00 UTC")

in, _ := time.Parse(time.RFC822, "01 Jan 15 20:00 UTC")
out, _ := time.Parse(time.RFC822, "01 Jan 17 10:00 UTC")

if inTimeSpan(start, end, in) {
fmt.Println(in, "is between", start, "and", end, ".")
}

if !inTimeSpan(start, end, out) {
fmt.Println(out, "is not between", start, "and", end, ".")
}
}

Go time comparison

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

Compare time in Go

By using time.After or time.Before.

Playground example:

package main

import (
"fmt"
"time"
)

func main() {
created := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
now := time.Now()
if created.Before(now) {
fmt.Println("do something")
}
}

Time comparison in Cypress

I notice you have the dayjs library. To handle parsing strings with various, add the customParseFormat plugin.

import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
dayjs.extend(customParseFormat)

Your dateString is passed into dayjs(dateString, format) as 1st parameter and format as 2nd parameter.

The .hours() method takes no parameters, it just extracts the hours portion.

I'm not sure exactly what format you have, so here's a few examples.

I've lined up the dateString and format so you can see the pattern.

// "Standard" format
const dateString1 = '2022-05-14 10:12:54'
const date1 = dayjs(dateString1, 'YYYY-MM-DD HH:mm:ss')
const hours1 = date1.hour()
console.log(hours1) // logs 10

// Dates with time in "10:12:54 AM" format
const dateString2 = '2022-05-14 10:12:54 AM'
const date2 = dayjs(dateString2, 'YYYY-MM-DD HH:mm:ss A')
const hours2 = date2.hour()
console.log(hours2) // logs 10

const dateString3 = '2022-05-14 1:12:54 PM'
const date3 = dayjs(dateString3, 'YYYY-MM-DD HH:mm:ss A')
const hours3 = date3.hour()
console.log(hours3) // logs 13

// Dates with time in "10AM" format
const dateString4 = '2022-05-14 10AM'
const date4 = dayjs(dateString4, 'YYYY-MM-DD HHA')
const hours4 = date4.hour()
console.log(hours4) // logs 10

const dateString5 = '2022-05-14 1PM'
const date5 = dayjs(dateString5, 'YYYY-MM-DD HHA')
const hours5 = date5.hour()
console.log(hours5) // logs 13

// Time-only strings
const timeString6 = '10:12:54 AM'
const date6 = dayjs(timeString6, 'HH:mm:ss A')
const hours6 = date6.hour()
console.log(hours6) // logs 10

const timeString7 = '1:12:54 PM'
const date7 = dayjs(timeString7, 'HH:mm:ss A')
const hours7 = date7.hour()
console.log(hours7) // logs 13

The full list of formats is here


I can't work out the layout of fixture file from your code.

In general, don't try to write and read intermediate values, it doesn't help you.

If you can control the format of the fixture file, you should separate fromDate and toDate with a comma which can be used to split the line

For example, cypress/fixtures/dates.txt

2022-05-14 10:12:54 AM, 2022-05-14 1:12:54 PM
... etc

Test:

cy.readFile('cypress/fixtures/dates.txt').then((dates) => {

const lines = dates.split('\n')

lines.forEach(line => {

const fromDateString = line.split(',')[0].trim()
const toDateString = line.split(',')[1].trim()

const fromDate = dayjs(fromDateString, 'YYYY-MM-DD HH:mm:ss A')
const toDate = dayjs(toDateString, 'YYYY-MM-DD HH:mm:ss A')

const timeDifference = toDate.diff(fromDate, "hour")
expect(timeDifference).to.equal(expectedDifference)
})
})

Note: toDate.diff(fromDate, "hour") will give a positive difference.

To compare with a negative difference, use the reverse

fromDate.diff(toDate, "hour")

Time comparison using strptime in Python

Value of then is 2021-07-19 21:39:07.876953\n.

Note the newline character at the end which you are not accounting for while using strptime.

You can fix it either by

  1. replacing \n with '' in then
then = open("service.txt","r").read().replace('\n', '')

  1. including \n in the date format string:
datetime.datetime.strptime(then, '%Y-%m-%d %H:%M:%S.%f\n')

Python datetime compare two time stamps without taking date into account

With exactly the code you have written, you're actually just going to be comparing two strings to one another since neither of them has been parsed as a datetime object.

Is there a specific reason that you explicitly do not want the date? If this is purely for comparison purposes, then the following should work since it will parse both times as being from the same date:

from datetime import datetime

time1 = datetime.strptime("16:00", "%H:%M")
time2 = datetime.strptime("17:00", "%H:%M")
print(time1)
print(time2)

Running this code prints:

1900-01-01 16:00:00
1900-01-01 17:00:00

and the underlying datetime objects can now be compared as you wanted.

Why is my python time comparison wrong every minute?

So the problem you're facing is due to how you're setting everything up. Basically, you're getting the 2 times' hour, minute, and second as a string, converting them to an int, and then subtracting their differences. Seconds only go up to 59 before going back to 00. So, when current_time_A's second is 59 and current_time_B's second is 00, the difference comes out to be 41 (because the minute changes as well).

Instead of converting back and forth between types (datetime.datetime -> str -> int), I suggest using time.time() to get the timestamp and do your calculations on that:

import time

while True:
current_time_A = time.time()
print(f"Current time A {current_time_A}")
time.sleep(1)
current_time_B = time.time()
print(f"Current time B: {current_time_B}")

# calculate how many seconds have elapsed since the start of the program
elapsed_time = current_time_B - current_time_A
print(f"Elapsed time: {elapsed_time}")
# round to the nearest second
print("Elapsed time (rounded):", round(elapsed_time))

Time Comparison between Python isPalindrome

To find out why a certain function is faster / slower in Python, always use dis.dis. The dis function from the standard dis module can disassemble the bytecode that a function has compiled into, so you can see what really happens when you run it.

Here is the disassembly of the three functions:

import dis
dis.dis(isPalindrome)
2 0 LOAD_CONST 1 (0)
2 LOAD_GLOBAL 0 (len)
4 LOAD_FAST 0 (value)
6 CALL_FUNCTION 1
8 LOAD_CONST 2 (1)
10 BINARY_SUBTRACT
12 ROT_TWO
14 STORE_FAST 1 (i)
16 STORE_FAST 2 (j)

3 18 LOAD_FAST 1 (i)
20 LOAD_FAST 2 (j)
22 COMPARE_OP 0 (<)
24 POP_JUMP_IF_FALSE 42 (to 84)
26 LOAD_FAST 0 (value)
28 LOAD_FAST 1 (i)
30 BINARY_SUBSCR
32 LOAD_FAST 0 (value)
34 LOAD_FAST 2 (j)
36 BINARY_SUBSCR
38 COMPARE_OP 2 (==)
40 POP_JUMP_IF_FALSE 42 (to 84)

4 >> 42 LOAD_FAST 1 (i)
44 LOAD_CONST 2 (1)
46 BINARY_ADD
48 LOAD_FAST 2 (j)
50 LOAD_CONST 2 (1)
52 BINARY_SUBTRACT
54 ROT_TWO
56 STORE_FAST 1 (i)
58 STORE_FAST 2 (j)

3 60 LOAD_FAST 1 (i)
62 LOAD_FAST 2 (j)
64 COMPARE_OP 0 (<)
66 POP_JUMP_IF_FALSE 42 (to 84)
68 LOAD_FAST 0 (value)
70 LOAD_FAST 1 (i)
72 BINARY_SUBSCR
74 LOAD_FAST 0 (value)
76 LOAD_FAST 2 (j)
78 BINARY_SUBSCR
80 COMPARE_OP 2 (==)
82 POP_JUMP_IF_TRUE 21 (to 42)

5 >> 84 LOAD_FAST 1 (i)
86 LOAD_FAST 2 (j)
88 COMPARE_OP 5 (>=)
90 RETURN_VALUE
dis.dis(isPalindrome2)
2 0 LOAD_FAST 0 (value)
2 LOAD_FAST 0 (value)
4 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
8 LOAD_CONST 1 (-1)
10 BUILD_SLICE 3
12 BINARY_SUBSCR
14 COMPARE_OP 2 (==)
16 RETURN_VALUE
dis.dis(isPalindrome3)
2 0 BUILD_LIST 0
2 STORE_FAST 1 (res)

3 4 LOAD_FAST 0 (value)
6 GET_ITER
>> 8 FOR_ITER 7 (to 24)
10 STORE_FAST 2 (c)

4 12 LOAD_FAST 1 (res)
14 LOAD_METHOD 0 (append)
16 LOAD_FAST 2 (c)
18 CALL_METHOD 1
20 POP_TOP
22 JUMP_ABSOLUTE 4 (to 8)

5 >> 24 LOAD_FAST 0 (value)
26 LOAD_CONST 1 ('')
28 LOAD_METHOD 1 (join)
30 LOAD_FAST 1 (res)
32 CALL_METHOD 1
34 COMPARE_OP 2 (==)
36 RETURN_VALUE

As you can see, isPalindrome2 has compiled to A LOT less bytecode than either of the other two. This is because most of its operations are builtin in Python, and therefore written in C, not in Python. The C code behind each of the operations in isPalindrome2 probably does a similar thing to the Python code in one of the other functions (although it is hard to tell), but it is much faster simply because C is a very fast language, and Python is very slow.

Bytes 4-13 of the isPalindrome2 bytecode do essentially the same thing as bytes 0-33 of the isPalindrome3 bytecode, but isPalindrome2 uses lots of operators that are handled by C code, whereas isPalindrome3 calls a Python function (very slow to do), loads a constant / variable 3 extra times, and uses a Python for loop. These things are all slower than their C equivalents, meaning it is slower. The same goes for the first function. Therefore, the second function, which has much less bytecode and mainly uses C code, is much faster.

Java8 time comparison in Kotlin

According to the documentation, when using the natively overloaded operators (comparison operators specifically) - Kotlin doesn't just call compareTo but rather performs a compareTo against 0 (thus ending up as a bool).

https://kotlinlang.org/docs/operator-overloading.html#comparison-operators

Comparison operators



Leave a reply



Submit