coveralls: 
[![Coverage Status](https://coveralls.io/builds/14460334/badge)](https://coveralls.io/builds/14460334)

Coverage decreased (-0.4%) to 97.977% when pulling **7e009b99ec957c63ed43f3ad059a07d895642162 on fix-issue-102** into **cec38fb58da280acfd66707e8c6438bb07b39d88 on master**.

codecov-io: # [Codecov](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=h1) Report
> Merging [#103](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=desc) into [master](https://codecov.io/gh/discos/simulators/commit/cec38fb58da280acfd66707e8c6438bb07b39d88?src=pr&el=desc) will **increase** coverage by `0.23%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/discos/simulators/pull/103/graphs/tree.svg?width=650&height=150&src=pr&token=UgIM6Vs2q5)](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #103      +/-   ##
==========================================
+ Coverage   98.41%   98.65%   +0.23%     
==========================================
  Files          11       11              
  Lines        2209     2300      +91     
==========================================
+ Hits         2174     2269      +95     
+ Misses         35       31       -4
```


| [Impacted Files](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [simulators/utils.py](https://codecov.io/gh/discos/simulators/pull/103/diff?src=pr&el=tree#diff-c2ltdWxhdG9ycy91dGlscy5weQ==) | `100% <100%> (+5.79%)` | :arrow_up: |
| [tests/test\_utils.py](https://codecov.io/gh/discos/simulators/pull/103/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF91dGlscy5weQ==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=footer). Last update [cec38fb...313820c](https://codecov.io/gh/discos/simulators/pull/103?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

coveralls: 
[![Coverage Status](https://coveralls.io/builds/14489780/badge)](https://coveralls.io/builds/14489780)

Coverage increased (+0.2%) to 98.652% when pulling **313820c0c109ef8f53c68f432379dd07a6b51b5a on fix-issue-102** into **cec38fb58da280acfd66707e8c6438bb07b39d88 on master**.

diff --git a/simulators/utils.py b/simulators/utils.py
index 1b7462c..35cf994 100644
--- a/simulators/utils.py
+++ b/simulators/utils.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
 import math
 import struct
 from datetime import datetime
@@ -144,16 +145,59 @@ def real_to_binary(num, precision=1):
         )
 
 
-def mjd():
-    """Return the modified julian date.
-    For more informations about modified julian date check the following link:
-    https://bowie.gsfc.nasa.gov/time/"""
+def real_to_bytes(num, precision=1):
+    """Return the bytestring representation of a floating-point number
+    (IEEE 754 standard)."""
+    binary_number = real_to_binary(num, precision)
+    return binary_to_bytes(binary_number)
 
-    utcnow = datetime.utcnow()
 
-    year = utcnow.year
-    month = utcnow.month
-    day = utcnow.day
+def bytes_to_real(bytes_real, precision=1):
+    """Return the floating-point representation (IEEE 754 standard)
+    of bytestring number."""
+    if precision == 1:
+        return struct.unpack('!f', bytes_real)[0]
+    elif precision == 2:
+        return struct.unpack('!d', bytes_real)[0]
+    else:
+        raise ValueError(
+            "Unknown precision %d."
+            % (precision)
+        )
+
+
+def int_to_bytes(val, n_bytes=4):
+    """Return the bytestring representation of a given signed integer."""
+    return binary_to_bytes(int_to_twos(val, n_bytes))
+
+
+def uint_to_bytes(val, n_bytes=4):
+    """Return the bytestring representation of a given unsigned integer."""
+    n_bits = 8 * n_bytes
+    min_range = 0
+    max_range = int(math.pow(2, n_bits)) - 1
+
+    if val < min_range or val > max_range:
+        raise ValueError(
+            "%d out of range (%d, %d)."
+            % (val, min_range, max_range)
+        )
+
+    return binary_to_bytes(bin(val)[2:].zfill(n_bytes * 8))
+
+
+def mjd(time=datetime.utcnow()):
+    """Returns the modified julian date (MJD) of a given datetime object.
+    If no datetime object is given, it returns the current MJD.
+    For more informations about modified julian date check the following link:
+    https://bowie.gsfc.nasa.gov/time/"""
+    year = time.year
+    month = time.month
+    day = time.day
+    hour = time.hour
+    minute = time.minute
+    second = time.second
+    microsecond = time.microsecond
 
     if month == 1 or month == 2:
         yearp = year - 1
@@ -173,11 +217,7 @@ def mjd():
         a = math.trunc(yearp / 100.)
         b = 2 - a + math.trunc(a / 4.)
 
-    if yearp < 0:
-        c = math.trunc((365.25 * yearp) - 0.75)
-    else:
-        c = math.trunc(365.25 * yearp)
-
+    c = math.trunc(365.25 * yearp)
     d = math.trunc(30.6001 * (monthp + 1))
 
     jd = b + c + d + day + 1720994.5
@@ -185,13 +225,13 @@ def mjd():
     modified_julian_day = jd - 2400000.5
 
     # Total UTC hours of the day
-    day_hours = utcnow.hour
+    day_hours = hour
     # Total minutes of the day
-    day_minutes = (day_hours * 60) + utcnow.minute
+    day_minutes = (day_hours * 60) + minute
     # Total seconds of the day
-    day_seconds = (day_minutes * 60) + utcnow.second
+    day_seconds = (day_minutes * 60) + second
     # Total microseconds of the day
-    day_microseconds = (day_seconds * 1000000) + utcnow.microsecond
+    day_microseconds = (day_seconds * 1000000) + microsecond
 
     # Day percentage, 00:00 = 0.0, 24:00=1.0
     day_percentage = round(float(day_microseconds) / 86400000000, 6)

Enhance `utils.py` to provide functions useful to the `acu.py` module.
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 65a8878..0f24101 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,4 +1,5 @@
 import unittest
+from datetime import datetime
 from simulators import utils
 
 
@@ -40,10 +41,23 @@ class TestServer(unittest.TestCase):
         with self.assertRaises(ValueError):
             utils.int_to_twos(4294967295)
 
-    def test_mjd(self):
+    def test_mjd_now(self):
         """Make sure that the datatype of the response is the correct one."""
         self.assertIsInstance(utils.mjd(), float)
 
+    def test_mjd_given_date(self):
+        """Return the modified julian date of a given datetime object."""
+        time = datetime(2017, 12, 4, 13, 51, 10, 162534)
+        result = utils.mjd(time)
+        expected_result = 58091.577201
+        self.assertEqual(result, expected_result)
+
+    def test_mjd_old_date(self):
+        time = datetime(1500, 1, 1, 12, 0, 0, 0)
+        result = utils.mjd(time)
+        expected_result = -131067.5
+        self.assertEqual(result, expected_result)
+
     def test_day_milliseconds(self):
         """Make sure that the datatype of the response is the correct one.
         Also make sure that the returned value is inside the expected range."""
@@ -88,7 +102,6 @@ class TestServer(unittest.TestCase):
         self.assertEqual(result, expected_result)
 
     def test_real_to_binary_double_precision(self):
-        """Convert a real number to its binary representation."""
         number = 3.14159265358979323846264338327950288419716939937510582097494
         result = utils.real_to_binary(number, 2)
         expected_result = (
@@ -109,5 +122,86 @@ class TestServer(unittest.TestCase):
         with self.assertRaises(ValueError):
             utils.real_to_binary(number, 3)
 
+    def test_real_to_bytes_single_precision(self):
+        """Convert a real number to a string of bytes."""
+        number = 45.12371938725634
+        result = utils.real_to_bytes(number)
+        expected_result = b'\x42\x34\x7E\xB0'
+        self.assertEqual(result, expected_result)
+
+    def test_real_to_bytes_double_precision(self):
+        number = 3.14159265358979323846264338327950288419716939937510582097494
+        result = utils.real_to_bytes(number, 2)
+        expected_result = b'\x40\x09\x21\xFB\x54\x44\x2D\x18'
+        self.assertEqual(result, expected_result)
+
+    def test_real_to_bytes_unknown_precision(self):
+        number = 3267.135248123736
+        with self.assertRaises(ValueError):
+            utils.real_to_binary(number, 3)
+
+    def test_bytes_to_real_single_precision(self):
+        """Convert a string of bytes to a floating point  number."""
+        byte_string = b'\x42\x34\x7E\xB0'
+        result = utils.bytes_to_real(byte_string)
+        expected_result = 45.12371826171875
+        self.assertEqual(result, expected_result)
+
+    def test_bytes_to_real_double_precision(self):
+        byte_string = b'\x40\x09\x21\xFB\x54\x44\x2D\x18'
+        result = utils.bytes_to_real(byte_string, 2)
+        expected_result = (
+            3.14159265358979323846264338327950288419716939937510582097494
+        )
+        self.assertEqual(result, expected_result)
+
+    def test_bytes_to_real_unknown_precision(self):
+        byte_string = b'\xDA\x35\xF7\x65'
+        with self.assertRaises(ValueError):
+            utils.bytes_to_real(byte_string, 3)
+
+    def test_int_to_bytes_positive(self):
+        """Convert a signed integer to a string of bytes."""
+        number = 232144
+        result = utils.int_to_bytes(number)
+        expected_result = b'\x00\x03\x8A\xD0'
+        self.assertEqual(result, expected_result)
+
+    def test_int_to_bytes_negative(self):
+        number = -4522764
+        result = utils.int_to_bytes(number)
+        expected_result = b'\xFF\xBA\xFC\xF4'
+        self.assertEqual(result, expected_result)
+
+    def test_int_to_bytes_out_of_range(self):
+        number = 36273463
+        with self.assertRaises(ValueError):
+            utils.int_to_bytes(number, 2)
+
+    def test_int_to_bytes_wrong(self):
+        number = 6814627
+        result = utils.int_to_bytes(number)
+        wrong_expected_result = b'\xFF\x98\x04\x5D'
+        self.assertNotEqual(result, wrong_expected_result)
+
+    def test_uint_to_bytes(self):
+        """Convert an unsigned integer to a string of bytes."""
+        number = 1284639736
+        result = utils.uint_to_bytes(number)
+        expected_result = b'\x4C\x92\x0B\xF8'
+        self.assertEqual(result, expected_result)
+
+    def test_uint_to_bytes_out_of_range(self):
+        number = 13463672713
+        with self.assertRaises(ValueError):
+            utils.uint_to_bytes(number)
+
+    def test_uint_to_bytes_wrong(self):
+        number = 1235326152
+        result = utils.uint_to_bytes(number)
+        wrong_expected_result = b'\x00\x34\xAE\xDD'
+        self.assertNotEqual(result, wrong_expected_result)
+
+
 if __name__ == '__main__':
     unittest.main()

pip install -e .[test]
parse_log_pytest
pytest
coverage prospector sphinx sphinx_rtd_theme tox pytest
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
astroid==3.3.9
babel==2.17.0
cachetools==5.5.2
certifi==2025.1.31
chardet==5.2.0
charset-normalizer==3.4.1
colorama==0.4.6
coverage==7.8.0
dill==0.3.9
-e git+https://github.com/discos/simulators.git@cec38fb58da280acfd66707e8c6438bb07b39d88#egg=discos_simulators
distlib==0.3.9
docutils==0.21.2
dodgy==0.2.1
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
filelock==3.18.0
flake8==7.2.0
flake8-polyfill==1.0.2
gitdb==4.0.12
GitPython==3.1.44
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
isort==6.0.1
Jinja2==3.1.6
MarkupSafe==3.0.2
mccabe==0.7.0
packaging @ file:///croot/packaging_1734472117206/work
pep8-naming==0.10.0
platformdirs==4.3.7
pluggy @ file:///croot/pluggy_1733169602837/work
prospector==1.16.1
pycodestyle==2.13.0
pydocstyle==6.3.0
pyflakes==3.3.2
Pygments==2.19.1
pylint==3.3.6
pylint-celery==0.3
pylint-django==2.6.1
pylint-plugin-utils==0.8.2
pyproject-api==1.9.0
pytest @ file:///croot/pytest_1738938843180/work
PyYAML==6.0.2
requests==2.32.3
requirements-detector==1.3.2
semver==3.0.4
setoptconf-tmp==0.3.1
smmap==5.0.2
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinx-rtd-theme==3.0.2
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
toml==0.10.2
tomli==2.2.1
tomlkit==0.13.2
tox==4.25.0
typing_extensions==4.13.0
urllib3==2.3.0
virtualenv==20.29.3
zipp==3.21.0

name: simulators
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.16
      - astroid==3.3.9
      - babel==2.17.0
      - cachetools==5.5.2
      - certifi==2025.1.31
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - colorama==0.4.6
      - coverage==7.8.0
      - dill==0.3.9
      - distlib==0.3.9
      - docutils==0.21.2
      - dodgy==0.2.1
      - filelock==3.18.0
      - flake8==7.2.0
      - flake8-polyfill==1.0.2
      - gitdb==4.0.12
      - gitpython==3.1.44
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - isort==6.0.1
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - pep8-naming==0.10.0
      - platformdirs==4.3.7
      - prospector==1.16.1
      - pycodestyle==2.13.0
      - pydocstyle==6.3.0
      - pyflakes==3.3.2
      - pygments==2.19.1
      - pylint==3.3.6
      - pylint-celery==0.3
      - pylint-django==2.6.1
      - pylint-plugin-utils==0.8.2
      - pyproject-api==1.9.0
      - pyyaml==6.0.2
      - requests==2.32.3
      - requirements-detector==1.3.2
      - semver==3.0.4
      - setoptconf-tmp==0.3.1
      - smmap==5.0.2
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinx-rtd-theme==3.0.2
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - toml==0.10.2
      - tomli==2.2.1
      - tomlkit==0.13.2
      - tox==4.25.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - zipp==3.21.0
prefix: /opt/conda/envs/simulators

tests/test_utils.py::TestServer::test_bytes_to_real_double_precision tests/test_utils.py::TestServer::test_bytes_to_real_single_precision tests/test_utils.py::TestServer::test_bytes_to_real_unknown_precision tests/test_utils.py::TestServer::test_int_to_bytes_out_of_range tests/test_utils.py::TestServer::test_mjd_given_date tests/test_utils.py::TestServer::test_mjd_old_date tests/test_utils.py::TestServer::test_uint_to_bytes_out_of_range
tests/test_utils.py::TestServer::test_binary_to_bytes_correct tests/test_utils.py::TestServer::test_binary_to_bytes_wrong tests/test_utils.py::TestServer::test_bytes_to_int_correct tests/test_utils.py::TestServer::test_bytes_to_int_wrong tests/test_utils.py::TestServer::test_day_milliseconds tests/test_utils.py::TestServer::test_int_to_bytes_negative tests/test_utils.py::TestServer::test_int_to_bytes_positive tests/test_utils.py::TestServer::test_int_to_bytes_wrong tests/test_utils.py::TestServer::test_real_to_binary_double_precision tests/test_utils.py::TestServer::test_real_to_binary_single_precision tests/test_utils.py::TestServer::test_real_to_binary_wrong tests/test_utils.py::TestServer::test_real_to_bytes_double_precision tests/test_utils.py::TestServer::test_real_to_bytes_single_precision tests/test_utils.py::TestServer::test_uint_to_bytes tests/test_utils.py::TestServer::test_uint_to_bytes_wrong
tests/test_utils.py::TestServer::test_int_to_twos tests/test_utils.py::TestServer::test_mjd_now tests/test_utils.py::TestServer::test_out_of_range_int_to_twos tests/test_utils.py::TestServer::test_real_to_binary_unknown_precision tests/test_utils.py::TestServer::test_real_to_bytes_unknown_precision tests/test_utils.py::TestServer::test_right_checksum tests/test_utils.py::TestServer::test_right_twos_to_int tests/test_utils.py::TestServer::test_wrong_checksum tests/test_utils.py::TestServer::test_wrong_twos_to_int
simulators/utils.py
simulators/utils.py