1

I have 2 timestamps represented as milliseconds in the last minute. Imagine there are no synchronization issues between nodes.

The receiver has to distinguish which is the first that was generated message. Unfortunately, after 59 seconds the variables restart, then how to compare these two variables?

Remark: imagine there is a max delay between the timers, i.e. 10 seconds. Otherwise the is no solution to this problem.

My solution is posted below.

DAme
  • 697
  • 8
  • 21
  • 1
    In the interest of appearances, a question probably should start with the question, not with the announcement "I want to post an answer but could not find the question." – JaMiT Sep 06 '20 at 11:03

2 Answers2

2

Comments in code below:

#include <limits.h>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

bool millis_in_last_minute_is_valid(int time) {
    // represented as milliseconds in the last minute
    // after 59 seconds the variables restart
    static_assert(INT_MAX > 59999, "Use long and not int to represent numbers greater then 2^16. int has __at least__ 16 bits, it may have 16 bits, in which case INT_MAX is around 32000, which will be lower then 59999 and not able to represent your timestamp");
    return 0 <= time && time <= 59999;
}

/**
 * @return true if time1 is happened before time2, false otherwise.
 */
bool timestamp_millis_in_last_minute_happened_before(int time1, int time2) {
    assert(millis_in_last_minute_is_valid(time1));
    assert(millis_in_last_minute_is_valid(time2));
    const int diff = abs(time2 - time1);
    // imagine there is a max delay between the timers, i.e. 10 seconds
    /**
    There are 4 cases:
        0---------time---------->60000
        [---------T1--T2-------->
        [---------T2--T1-------->
        [-T2-----------------T1->
        [-T1-----------------T2->
    If the difference is smaller then 10 seconds, it's 
    one of two first cases, if it's grater then 10 seconds,
    it's one of the latter. If the latter, the comparison
    needs to just be inverted.
    */
    // assert the difference between timestamps is max 10 seconds
    assert(
        // First two cases
        (0 <= diff && diff <= 10000) ||
        // Latter two cases
        (50000 <= diff && diff < 60000));
    return diff <= 10000 ? time1 < time2 : time2 < time1;
}

int main() {
    // simple test cases with assert
    // 0 is not lower then 0         |T1T2------->     T1 happened with T2
    assert(timestamp_millis_in_last_minute_happened_before(0, 0) == 0);
    // 1 is not lower then 0         |T2-T1------>     T1 happened after T2
    assert(timestamp_millis_in_last_minute_happened_before(1, 0) == 0);
    // 0 is lower then 1             |T1-T2------>     T1 happened before T2
    assert(timestamp_millis_in_last_minute_happened_before(0, 1) == 1);
    // 59 second happens before 1    |T2------T1->     T1 happened before T2
    assert(timestamp_millis_in_last_minute_happened_before(59000, 1) == 1);
    // 1 happens before 59 second    |T1------T2->     T1 happened before T2
    assert(timestamp_millis_in_last_minute_happened_before(1, 59000) == 0);
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
0

Here is my solution:

int compare_timestamp_millis_in_last_minute(int time1, int time2)
{ 
   if(time1 == time2) return 0;

   int millisInLastMinute = get_time_in_millis() % MAXMILLISINMINUTE;

   if((time1 - millisInLastMinute % MAXMILLISINMINUTE) > (time2 - millisInLastMinute % MAXMILLISINMINUTE))
      return 1;
   else
      return -1;
}

with MAXMILLISINMINUTE = 65535

Idea behind solution: time1 and time 2 are always less than the time at the moment of comparation. Then subtracting a time that is after will move the time1 and time 2 variable in the left quadrant (both less or equal to 59 s).

Anyone has a different solution?

DAme
  • 697
  • 8
  • 21
  • 1
    A brief description of how it works would be nice. – πάντα ῥεῖ Sep 06 '20 at 10:15
  • 1
    What is this magic `65536` number? – KamilCuk Sep 06 '20 at 10:17
  • Also I am not so convinced that you met the required Q&A format properly here. An answer shouldn't introduce a new question, that rather seems to belong into the question, and go to [Code Review](https://codereview.stackexchange.com/) altogether. – πάντα ῥεῖ Sep 06 '20 at 10:18
  • Added a description of the solution – DAme Sep 06 '20 at 10:24
  • 1
    I still don't get it. Why `65536`? Would it work with `65535`? – KamilCuk Sep 06 '20 at 10:26
  • Yes, sorry 65535 (a constant should be better) I'll fix it – DAme Sep 06 '20 at 10:28
  • 2
    Why is `MAXMILLISINMINUTE` equal to `65535`? A minute has 60000 milliseconds, no? Why do you need _current_ time to compare some timestamp? – KamilCuk Sep 06 '20 at 10:30
  • 1
    I use MAXMILLISINMINUTE equal to 65535 cause timestamps are usual expressed as time passed since a refence time (e.g. EPOCH: 1970 or TAI: 2004), then is simple to cut the last 16 bit to obtain the last minute in millis. This is commonly used in some libraries. – DAme Sep 06 '20 at 11:20
  • @DAme Even if that is common, the question specifically states "milliseconds in the last minute". Answers should match the question, absent a compelling reason to do otherwise. Even when it is your own question. – JaMiT Sep 06 '20 at 11:27
  • 1
    "simple to cut the last 16 bit to obtain the last minute in millis." is not accomplished by `MAXMILLISINMINUTE = 65535` and `millisInLastMinute % MAXMILLISINMINUTE`. Off by 1. Should be 65536 and type should be `unsigned`. – chux - Reinstate Monica Sep 10 '20 at 04:55