Repository: prometheus/client_python

Issue:
Timestamp comparison is wrong
Currently, `samples.Timestamp` implementation for comparisons is:

```
    def __gt__(self, other: "Timestamp") -> bool:
        return self.sec > other.sec or self.nsec > other.nsec

    def __lt__(self, other: "Timestamp") -> bool:
        return self.sec < other.sec or self.nsec < other.nsec
```

what might not compare correctly. Example:

```
>>> a = Timestamp(2, 5)
>>> b = Timestamp(3, 4)
>>> a > b
True
```

In the example, the first part is `2<3`, what is false, forcing to perform the next part, what is `5>4`, returning `True`.

A good implementation could be:
```
    def __gt__(self, other: "Timestamp") -> bool:
        if self.sec == other.sec:
            return self.nsec > other.nsec
        return self.sec > other.sec

    def __lt__(self, other: "Timestamp") -> bool:
        if self.sec == other.sec:
            return self.nsec < other.nsec
        return self.sec < other.sec
```

Another option, perhaps even better, is to rely on python's tuples implementation:
```
    def __gt__(self, other: "Timestamp") -> bool:
        return (self.sec, self.nsec) > (other.sec, other.nsec)

    def __lt__(self, other: "Timestamp") -> bool:
        return (self.sec, self.nsec) < (other.sec, other.nsec)
```

Discussion:

Solution patch:
diff --git a/docs/content/exporting/http/asgi.md b/docs/content/exporting/http/asgi.md
index 4ff115e..5b9d543 100644
--- a/docs/content/exporting/http/asgi.md
+++ b/docs/content/exporting/http/asgi.md
@@ -14,10 +14,10 @@ app = make_asgi_app()
 Such an application can be useful when integrating Prometheus metrics with ASGI
 apps.
 
-By default, the WSGI application will respect `Accept-Encoding:gzip` headers used by Prometheus
+By default, the ASGI application will respect `Accept-Encoding:gzip` headers used by Prometheus
 and compress the response if such a header is present. This behaviour can be disabled by passing 
 `disable_compression=True` when creating the app, like this:
 
 ```python
 app = make_asgi_app(disable_compression=True)
-```
\ No newline at end of file
+```
diff --git a/prometheus_client/samples.py b/prometheus_client/samples.py
index 8735fed..53c4726 100644
--- a/prometheus_client/samples.py
+++ b/prometheus_client/samples.py
@@ -28,10 +28,10 @@ class Timestamp:
         return not self == other
 
     def __gt__(self, other: "Timestamp") -> bool:
-        return self.sec > other.sec or self.nsec > other.nsec
+        return self.nsec > other.nsec if self.sec == other.sec else self.sec > other.sec
 
     def __lt__(self, other: "Timestamp") -> bool:
-        return self.sec < other.sec or self.nsec < other.nsec
+        return self.nsec < other.nsec if self.sec == other.sec else self.sec < other.sec
 
 
 # Timestamp and exemplar are optional.


Test patch:
diff --git a/tests/test_samples.py b/tests/test_samples.py
index 796afe7..7b59218 100644
--- a/tests/test_samples.py
+++ b/tests/test_samples.py
@@ -12,6 +12,8 @@ class TestSamples(unittest.TestCase):
         self.assertEqual(samples.Timestamp(1, 2) > samples.Timestamp(1, 1), True)
         self.assertEqual(samples.Timestamp(2, 1) > samples.Timestamp(1, 1), True)
         self.assertEqual(samples.Timestamp(2, 2) > samples.Timestamp(1, 1), True)
+        self.assertEqual(samples.Timestamp(0, 2) > samples.Timestamp(1, 1), False)
+        self.assertEqual(samples.Timestamp(2, 0) > samples.Timestamp(1, 1), True)
 
     def test_lt(self):
         self.assertEqual(samples.Timestamp(1, 1) < samples.Timestamp(1, 1), False)
@@ -21,6 +23,8 @@ class TestSamples(unittest.TestCase):
         self.assertEqual(samples.Timestamp(1, 2) < samples.Timestamp(1, 1), False)
         self.assertEqual(samples.Timestamp(2, 1) < samples.Timestamp(1, 1), False)
         self.assertEqual(samples.Timestamp(2, 2) < samples.Timestamp(1, 1), False)
+        self.assertEqual(samples.Timestamp(0, 2) < samples.Timestamp(1, 1), True)
+        self.assertEqual(samples.Timestamp(2, 0) < samples.Timestamp(1, 1), False)
 
 
 if __name__ == '__main__':