gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: introducing GNUNET_TIME_Timestamp


From: gnunet
Subject: [gnunet] branch master updated: introducing GNUNET_TIME_Timestamp
Date: Tue, 14 Dec 2021 15:59:17 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 99779b455 introducing GNUNET_TIME_Timestamp
99779b455 is described below

commit 99779b455ce3bf9c53dd411575766bf298a3a5f3
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Tue Dec 14 15:59:07 2021 +0100

    introducing GNUNET_TIME_Timestamp
---
 src/curl/curl.c                  | 196 +-----------------------------
 src/include/gnunet_getopt_lib.h  |  18 +++
 src/include/gnunet_json_lib.h    |  38 +++---
 src/include/gnunet_pq_lib.h      |  53 ++++++++-
 src/include/gnunet_sq_lib.h      |  10 +-
 src/include/gnunet_strings_lib.h |  19 ++-
 src/include/gnunet_time_lib.h    | 220 +++++++++++++++++++++++++++++++---
 src/json/json_generator.c        |  86 +++++---------
 src/json/json_helper.c           | 124 ++++++++++---------
 src/json/json_pack.c             |  16 +--
 src/json/test_json.c             |  70 ++++++-----
 src/pq/pq_query_helper.c         | 107 +++++++++++++++--
 src/pq/pq_result_helper.c        | 142 ++++++++++++++++++++++
 src/util/Makefile.am             |   2 +-
 src/util/getopt_helpers.c        | 249 +++++++++++++--------------------------
 src/util/strings.c               |  22 +++-
 src/util/time.c                  | 218 +++++++++++++++++++++++++++++-----
 17 files changed, 979 insertions(+), 611 deletions(-)

diff --git a/src/curl/curl.c b/src/curl/curl.c
index 684610101..e45612e94 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -201,14 +201,6 @@ struct GNUNET_CURL_Context
 };
 
 
-/**
- * Force use of the provided username and password
- * for client authentication for all operations performed
- * with @a ctx.
- *
- * @param ctx context to set authentication data for
- * @param userpass string with "$USERNAME:$PASSWORD"
- */
 void
 GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
                           const char *userpass)
@@ -219,21 +211,6 @@ GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Force use of the provided TLS client certificate
- * for client authentication for all operations performed
- * with @a ctx.
- *
- * Note that if the provided information is incorrect,
- * the earliest operation that could fail is
- * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()!
- *
- * @param ctx context to set authentication data for
- * @param certtype type of the certificate
- * @param certfile file with the certificate
- * @param keyfile file with the private key
- * @param keypass passphrase to decrypt @a keyfile (or NULL)
- */
 void
 GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
                          const char *certtype,
@@ -256,14 +233,6 @@ GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Initialise this library.  This function should be called before using any of
- * the following functions.
- *
- * @param cb function to call when rescheduling is required
- * @param cb_cls closure for @a cb
- * @return library context
- */
 struct GNUNET_CURL_Context *
 GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
                   void *cb_cls)
@@ -299,12 +268,6 @@ GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
 }
 
 
-/**
- * Enable sending the async scope ID as a header.
- *
- * @param ctx the context to enable this for
- * @param header_name name of the header to send.
- */
 void
 GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx,
                                        const char *header_name)
@@ -313,15 +276,6 @@ GNUNET_CURL_enable_async_scope_header (struct 
GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Return #GNUNET_YES if given a valid scope ID and
- * #GNUNET_NO otherwise.  See #setup_job_headers,
- * logic related to
- * #GNUNET_CURL_enable_async_scope_header() for the
- * code that generates such a @a scope_id.
- *
- * @returns #GNUNET_YES iff given a valid scope ID
- */
 int
 GNUNET_CURL_is_valid_scope_id (const char *scope_id)
 {
@@ -447,7 +401,9 @@ setup_job (CURL *eh,
   struct GNUNET_CURL_Job *job;
 
   if (CURLE_OK !=
-      curl_easy_setopt (eh, CURLOPT_HTTPHEADER, all_headers))
+      curl_easy_setopt (eh,
+                        CURLOPT_HTTPHEADER,
+                        all_headers))
   {
     GNUNET_break (0);
     curl_slist_free_all (all_headers);
@@ -491,12 +447,6 @@ setup_job (CURL *eh,
 }
 
 
-/**
- * Add @a extra_headers to the HTTP headers for @a job.
- *
- * @param[in,out] job the job to modify
- * @param extra_headers headers to append
- */
 void
 GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
                             const struct curl_slist *extra_headers)
@@ -515,21 +465,6 @@ GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
 }
 
 
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion.  Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.  Used to download
- * resources that are NOT in JSON.  The raw body will be returned.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- *           be executed AND cleaned up
- * @param job_headers extra headers to add for this request
- * @param max_reply_size largest acceptable response body
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
 struct GNUNET_CURL_Job *
 GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
                          CURL *eh,
@@ -554,25 +489,6 @@ GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion.  Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.
- *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header if @a add_json is set.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will be executed AND
- *           cleaned up.  NOTE: the handle should _never_ have gotten
- *           any headers list, as that would then be overridden by
- *           @a jcc.  Therefore, always pass custom headers as the
- *           @a job_headers parameter.
- * @param job_headers extra headers to add for this request
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
 struct GNUNET_CURL_Job *
 GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
                       CURL *eh,
@@ -624,21 +540,6 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion.  Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.
- *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- *           be executed AND cleaned up
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
 struct GNUNET_CURL_Job *
 GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
                                   CURL *eh,
@@ -661,18 +562,6 @@ GNUNET_CURL_job_add_with_ct_json (struct 
GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion.  Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- *           be executed AND cleaned up
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
 struct GNUNET_CURL_Job *
 GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
                      CURL *eh,
@@ -687,12 +576,6 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Cancel a job.  Must only be called before the job completion
- * callback is called for the respective job.
- *
- * @param job job to cancel
- */
 void
 GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job)
 {
@@ -746,24 +629,6 @@ is_json (const char *ct)
 }
 
 
-/**
- * Obtain information about the final result about the
- * HTTP download. If the download was successful, parses
- * the JSON in the @a db and returns it. Also returns
- * the HTTP @a response_code.  If the download failed,
- * the return value is NULL.  The response code is set
- * in any case, on download errors to zero.
- *
- * Calling this function also cleans up @a db.
- *
- * @param db download buffer
- * @param eh CURL handle (to get the response code)
- * @param[out] response_code set to the HTTP response code
- *             (or zero if we aborted the download, for example
- *              because the response was too big, or if
- *              the JSON we received was malformed).
- * @return NULL if downloading a JSON reply failed.
- */
 void *
 GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
                                   CURL *eh,
@@ -838,13 +703,6 @@ GNUNET_CURL_download_get_result_ (struct 
GNUNET_CURL_DownloadBuffer *db,
 }
 
 
-/**
- * Add custom request header.
- *
- * @param ctx cURL context.
- * @param header header string; will be given to the context AS IS.
- * @return #GNUNET_OK if no errors occurred, #GNUNET_SYSERR otherwise.
- */
 enum GNUNET_GenericReturnValue
 GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
                            const char *header)
@@ -858,14 +716,6 @@ GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Run the main event loop for the HTTP interaction.
- *
- * @param ctx the library context
- * @param rp parses the raw response returned from
- *        the Web server.
- * @param rc cleans/frees the response
- */
 void
 GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
                       GNUNET_CURL_RawParser rp,
@@ -920,11 +770,6 @@ GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
 }
 
 
-/**
- * Run the main event loop for the HTTP interaction.
- *
- * @param ctx the library context
- */
 void
 GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
 {
@@ -934,34 +779,6 @@ GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
 }
 
 
-/**
- * Obtain the information for a select() call to wait until
- * #GNUNET_CURL_perform() is ready again.  Note that calling
- * any other GNUNET_CURL-API may also imply that the library
- * is again ready for #GNUNET_CURL_perform().
- *
- * Basically, a client should use this API to prepare for select(),
- * then block on select(), then call #GNUNET_CURL_perform() and then
- * start again until the work with the context is done.
- *
- * This function will NOT zero out the sets and assumes that @a max_fd
- * and @a timeout are already set to minimal applicable values.  It is
- * safe to give this API FD-sets and @a max_fd and @a timeout that are
- * already initialized to some other descriptors that need to go into
- * the select() call.
- *
- * @param ctx context to get the event loop information for
- * @param read_fd_set will be set for any pending read operations
- * @param write_fd_set will be set for any pending write operations
- * @param except_fd_set is here because curl_multi_fdset() has this argument
- * @param max_fd set to the highest FD included in any set;
- *        if the existing sets have no FDs in it, the initial
- *        value should be "-1". (Note that `max_fd + 1` will need
- *        to be passed to select().)
- * @param timeout set to the timeout in milliseconds (!); -1 means
- *        no timeout (NULL, blocking forever is OK), 0 means to
- *        proceed immediately with #GNUNET_CURL_perform().
- */
 void
 GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx,
                              fd_set *read_fd_set,
@@ -995,13 +812,6 @@ GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context 
*ctx,
 }
 
 
-/**
- * Cleanup library initialisation resources.  This function should be called
- * after using this library to cleanup the resources occupied during library's
- * initialisation.
- *
- * @param ctx the library context
- */
 void
 GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx)
 {
diff --git a/src/include/gnunet_getopt_lib.h b/src/include/gnunet_getopt_lib.h
index 731be4159..259d648dd 100644
--- a/src/include/gnunet_getopt_lib.h
+++ b/src/include/gnunet_getopt_lib.h
@@ -377,6 +377,24 @@ GNUNET_GETOPT_option_absolute_time (char shortName,
                                     struct GNUNET_TIME_Absolute *val);
 
 
+/**
+ * Allow user to specify a `struct GNUNET_TIME_Timestamp`
+ * (using human-readable "fancy" time).
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val set to the time specified at the command line
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_timestamp (char shortName,
+                                const char *name,
+                                const char *argumentHelp,
+                                const char *description,
+                                struct GNUNET_TIME_Timestamp *val);
+
+
 /**
  * Increment @a val each time the option flag is given by one.
  *
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h
index 5ef4592e5..7d101196c 100644
--- a/src/include/gnunet_json_lib.h
+++ b/src/include/gnunet_json_lib.h
@@ -304,25 +304,25 @@ GNUNET_JSON_spec_boolean (const char *name,
 /* ************ GNUnet-specific parser specifications ******************* */
 
 /**
- * Absolute time.
+ * Timestamp.
  *
  * @param name name of the JSON field
  * @param[out] at where to store the absolute time found under @a name
  */
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_absolute_time (const char *name,
-                                struct GNUNET_TIME_Absolute *at);
+GNUNET_JSON_spec_timestamp (const char *name,
+                            struct GNUNET_TIME_Timestamp *t);
 
 
 /**
- * Absolute time in network byte order.
+ * Timestamp in network byte order.
  *
  * @param name name of the JSON field
- * @param[out] at where to store the absolute time found under @a name
+ * @param[out] tn where to store the absolute time found under @a name
  */
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_absolute_time_nbo (const char *name,
-                                    struct GNUNET_TIME_AbsoluteNBO *at);
+GNUNET_JSON_spec_timestamp_nbo (const char *name,
+                                struct GNUNET_TIME_TimestampNBO *tn);
 
 
 /**
@@ -385,23 +385,23 @@ GNUNET_JSON_from_data (const void *data, size_t size);
 
 
 /**
- * Convert absolute timestamp to a json string.
+ * Convert timestamp to a json string.
  *
  * @param stamp the time stamp
  * @return a json string with the timestamp in @a stamp
  */
 json_t *
-GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp);
+GNUNET_JSON_from_timestamp (struct GNUNET_TIME_Timestamp stamp);
 
 
 /**
- * Convert absolute timestamp to a json string.
+ * Convert timestamp to a json string.
  *
  * @param stamp the time stamp
  * @return a json string with the timestamp in @a stamp
  */
 json_t *
-GNUNET_JSON_from_time_abs_nbo (struct GNUNET_TIME_AbsoluteNBO stamp);
+GNUNET_JSON_from_timestamp_nbo (struct GNUNET_TIME_TimestampNBO stamp);
 
 
 /**
@@ -747,30 +747,30 @@ GNUNET_JSON_pack_data_varsize (const char *name,
 
 /**
  * Generate packer instruction for a JSON field of type
- * absolute time.
+ * timestamp.
  *
  * @param name name of the field to add to the object
- * @param at absolute time to pack, a value of 0 is only
+ * @param at timestamp pack, a value of 0 is only
  *        allowed with #GNUNET_JSON_pack_allow_null()!
  * @return json pack specification
  */
 struct GNUNET_JSON_PackSpec
-GNUNET_JSON_pack_time_abs (const char *name,
-                           struct GNUNET_TIME_Absolute at);
+GNUNET_JSON_pack_timestamp (const char *name,
+                            struct GNUNET_TIME_Timestamp at);
 
 
 /**
  * Generate packer instruction for a JSON field of type
- * absolute time in network byte order.
+ * timestamp in network byte order.
  *
  * @param name name of the field to add to the object
- * @param at absolute time to pack, a value of 0 is only
+ * @param at timestamp to pack, a value of 0 is only
  *        allowed with #GNUNET_JSON_pack_allow_null()!
  * @return json pack specification
  */
 struct GNUNET_JSON_PackSpec
-GNUNET_JSON_pack_time_abs_nbo (const char *name,
-                               struct GNUNET_TIME_AbsoluteNBO at);
+GNUNET_JSON_pack_timestamp_nbo (const char *name,
+                                struct GNUNET_TIME_TimestampNBO at);
 
 
 /**
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h
index 05d373f88..f7bf59212 100644
--- a/src/include/gnunet_pq_lib.h
+++ b/src/include/gnunet_pq_lib.h
@@ -96,7 +96,11 @@ struct GNUNET_PQ_QueryParam
  */
 #define GNUNET_PQ_query_param_end \
   {                               \
-    NULL, NULL, NULL, 0, 0        \
+    .conv = NULL,                 \
+    .conv_cls = NULL,             \
+    .data = NULL,                 \
+    .size = 0,                    \
+    .num_params = 0               \
   }
 
 
@@ -199,6 +203,17 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x);
 
 
+/**
+ * Generate query parameter for a timestamp.
+ * The database must store a 64-bit integer.
+ *
+ * @param x pointer to the query parameter to pass
+ * @return query parameter to use
+ */
+struct GNUNET_PQ_QueryParam
+GNUNET_PQ_query_param_timestamp (const struct GNUNET_TIME_Timestamp *x);
+
+
 /**
  * Generate query parameter for an absolute time value.
  * The database must store a 64-bit integer.
@@ -211,6 +226,18 @@ GNUNET_PQ_query_param_absolute_time_nbo (
   const struct GNUNET_TIME_AbsoluteNBO *x);
 
 
+/**
+ * Generate query parameter for a timestamp in NBO.
+ * The database must store a 64-bit integer.
+ *
+ * @param x pointer to the query parameter to pass
+ * @return query parameter to use
+ */
+struct GNUNET_PQ_QueryParam
+GNUNET_PQ_query_param_timestamp_nbo (
+  const struct GNUNET_TIME_TimestampNBO *t);
+
+
 /**
  * Generate query parameter for an uint16_t in host byte order.
  *
@@ -471,6 +498,18 @@ GNUNET_PQ_result_spec_absolute_time (const char *name,
                                      struct GNUNET_TIME_Absolute *at);
 
 
+/**
+ * Timestamp expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] t where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+GNUNET_PQ_result_spec_timestamp (const char *name,
+                                 struct GNUNET_TIME_Timestamp *t);
+
+
 /**
  * Relative time expected.
  *
@@ -495,6 +534,18 @@ GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
                                          struct GNUNET_TIME_AbsoluteNBO *at);
 
 
+/**
+ * Timestamp expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] tn where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+GNUNET_PQ_result_spec_timestamp_nbo (const char *name,
+                                     struct GNUNET_TIME_TimestampNBO *tn);
+
+
 /**
  * uint16_t expected.
  *
diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h
index 21ce5b393..e89ded07e 100644
--- a/src/include/gnunet_sq_lib.h
+++ b/src/include/gnunet_sq_lib.h
@@ -40,7 +40,7 @@
  *            so immediately suitable for passing to `sqlite3_bind`-functions.
  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  */
-typedef int
+typedef enum GNUNET_GenericReturnValue
 (*GNUNET_SQ_QueryConverter)(void *cls,
                             const void *data,
                             size_t data_len,
@@ -156,8 +156,8 @@ GNUNET_SQ_query_param_absolute_time (const struct 
GNUNET_TIME_Absolute *x);
  * @param x pointer to the query parameter to pass
  */
 struct GNUNET_SQ_QueryParam
-GNUNET_SQ_query_param_absolute_time_nbo (const struct
-                                         GNUNET_TIME_AbsoluteNBO *x);
+GNUNET_SQ_query_param_absolute_time_nbo (
+  const struct GNUNET_TIME_AbsoluteNBO *x);
 
 
 /**
@@ -222,7 +222,7 @@ GNUNET_SQ_reset (sqlite3 *dbh,
  *   #GNUNET_YES if all results could be extracted
  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  */
-typedef int
+typedef enum GNUNET_GenericReturnValue
 (*GNUNET_SQ_ResultConverter)(void *cls,
                              sqlite3_stmt *result,
                              unsigned int column,
@@ -436,7 +436,7 @@ GNUNET_SQ_result_spec_uint64 (uint64_t *u64);
  *   #GNUNET_OK if all results could be extracted
  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_SQ_extract_result (sqlite3_stmt *result,
                           struct GNUNET_SQ_ResultSpec *rs);
 
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 977c2ead7..2e0c720ee 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -76,7 +76,7 @@ GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
  * @param rtime set to the relative time
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
                                        struct GNUNET_TIME_Relative *rtime);
 
@@ -91,11 +91,26 @@ GNUNET_STRINGS_fancy_time_to_relative (const char 
*fancy_time,
  * @param atime set to the absolute time
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
                                        struct GNUNET_TIME_Absolute *atime);
 
 
+/**
+ * @ingroup time
+ * Convert a given fancy human-readable time to our internal
+ * representation.  The human-readable time is expected to be
+ * in local time, whereas the returned value will be in UTC.
+ *
+ * @param fancy_time human readable string (e.g. %Y-%m-%d %H:%M:%S)
+ * @param atime set to the absolute time
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_STRINGS_fancy_time_to_timestamp (const char *fancy_time,
+                                        struct GNUNET_TIME_Timestamp *atime);
+
+
 /**
  * Convert a given filesize into a fancy human-readable format.
  *
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h
index 26b442066..5e826ace0 100644
--- a/src/include/gnunet_time_lib.h
+++ b/src/include/gnunet_time_lib.h
@@ -53,6 +53,17 @@ struct GNUNET_TIME_Absolute
   uint64_t abs_value_us;
 };
 
+/**
+ * Rounded time for timestamps used by GNUnet, in seconds.
+ */
+struct GNUNET_TIME_Timestamp
+{
+  /**
+   * The actual value. Must be round number in seconds.
+   */
+  struct GNUNET_TIME_Absolute abs_time;
+};
+
 /**
  * Time for relative time used by GNUnet, in microseconds.
  * Always positive, so we can only refer to future time.
@@ -89,17 +100,34 @@ struct GNUNET_TIME_AbsoluteNBO
    */
   uint64_t abs_value_us__ GNUNET_PACKED;
 };
+
+/**
+ * Time for timestamps used by GNUnet, in seconds and in network byte order.
+ */
+struct GNUNET_TIME_TimestampNBO
+{
+  /**
+   * The actual value. Must be round number in seconds.
+   */
+  struct GNUNET_TIME_AbsoluteNBO abs_time_nbo;
+};
+
 GNUNET_NETWORK_STRUCT_END
 
 /**
  * Relative time zero.
  */
-#define GNUNET_TIME_UNIT_ZERO     GNUNET_TIME_relative_get_zero_ ()
+#define GNUNET_TIME_UNIT_ZERO ((struct GNUNET_TIME_Relative){0})
 
 /**
  * Absolute time zero.
  */
-#define GNUNET_TIME_UNIT_ZERO_ABS GNUNET_TIME_absolute_get_zero_ ()
+#define GNUNET_TIME_UNIT_ZERO_ABS ((struct GNUNET_TIME_Absolute){0})
+
+/**
+ * Timestamp of zero.
+ */
+#define GNUNET_TIME_UNIT_ZERO_TS ((struct GNUNET_TIME_Timestamp){{0}})
 
 /**
  * One microsecond, our basic time unit.
@@ -154,13 +182,22 @@ GNUNET_NETWORK_STRUCT_END
  * Constant used to specify "forever".  This constant
  * will be treated specially in all time operations.
  */
-#define GNUNET_TIME_UNIT_FOREVER_REL GNUNET_TIME_relative_get_forever_ ()
+#define GNUNET_TIME_UNIT_FOREVER_REL \
+  ((struct GNUNET_TIME_Relative){UINT64_MAX})
 
 /**
  * Constant used to specify "forever".  This constant
  * will be treated specially in all time operations.
  */
-#define GNUNET_TIME_UNIT_FOREVER_ABS GNUNET_TIME_absolute_get_forever_ ()
+#define GNUNET_TIME_UNIT_FOREVER_ABS \
+  ((struct GNUNET_TIME_Absolute){UINT64_MAX})
+
+/**
+ * Constant used to specify "forever".  This constant
+ * will be treated specially in all time operations.
+ */
+#define GNUNET_TIME_UNIT_FOREVER_TS \
+  ((struct GNUNET_TIME_Timestamp){{UINT64_MAX}})
 
 
 /**
@@ -182,6 +219,47 @@ GNUNET_NETWORK_STRUCT_END
       GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, (r)), 2))
 
 
+/**
+ * Convert @a ts to human-readable timestamp.
+ * Note that the returned value will be overwritten if this function
+ * is called again.
+ *
+ * @param ts the timestamp to convert
+ * @return statically allocated string, will change on the next call
+ */
+const char *
+GNUNET_TIME_timestamp2s (struct GNUNET_TIME_Timestamp ts);
+
+
+/**
+ * @ingroup time
+ * Like `asctime`, except for GNUnet time.  Converts a GNUnet internal
+ * absolute time (which is in UTC) to a string in local time.
+ * Note that the returned value will be overwritten if this function
+ * is called again.
+ *
+ * @param t the absolute time to convert
+ * @return timestamp in human-readable form in local time
+ */
+const char *
+GNUNET_TIME_absolute2s (struct GNUNET_TIME_Absolute ts);
+
+
+/**
+ * @ingroup time
+ * Give relative time in human-readable fancy format.
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param delta time in milli seconds
+ * @param do_round are we allowed to round a bit?
+ * @return string in human-readable form
+ */
+const char *
+GNUNET_TIME_relative2s (struct GNUNET_TIME_Relative delta,
+                        bool do_round);
+
+
 /**
  * Randomized exponential back-off, starting at 1 ms
  * and going up by a factor of 2+r, where 0 <= r <= 0.5, up
@@ -192,8 +270,8 @@ GNUNET_NETWORK_STRUCT_END
  * @return the next backoff time
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt, struct
-                                GNUNET_TIME_Relative threshold);
+GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
+                                struct GNUNET_TIME_Relative threshold);
 
 
 /**
@@ -290,27 +368,69 @@ GNUNET_TIME_relative_to_absolute (struct 
GNUNET_TIME_Relative rel);
 
 
 /**
- * Round a time value so that it is suitable for transmission
- * via JSON encodings.
+ * Convert relative time to a timestamp in the
+ * future.
+ *
+ * @param rel relative time to convert
+ * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER 
(or if we would overflow)
+ */
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_relative_to_timestamp (struct GNUNET_TIME_Relative rel);
+
+
+/**
+ * Round an absolute time to a timestamp.
  *
  * @param at time to round
- * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
- *         it was just now rounded
+ * @return the result
  */
-int
-GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at);
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at);
 
 
 /**
- * Round a time value so that it is suitable for transmission
- * via JSON encodings.
+ * Get timestamp representing the current time.
  *
- * @param rt time to round
- * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
- *         it was just now rounded
+ * @return current time, rounded down to seconds
  */
-int
-GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt);
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_get (void);
+
+
+/**
+ * Compare two absolute times.
+ *
+ * @param t1 first time
+ * @param op compare operator
+ * @param t2 second time
+ * @return true if @a t1 @a op @a t2
+ */
+#define GNUNET_TIME_absolute_cmp(t1,op,t2) \
+  (((void) (1 op 2), (t1).abs_value_us op (t2).abs_value_us))
+
+
+/**
+ * Compare two timestamps
+ *
+ * @param t1 first timestamp
+ * @param op compare operator
+ * @param t2 second timestamp
+ * @return true if @a t1 @a op @a t2
+ */
+#define GNUNET_TIME_timestamp_cmp(t1,op,t2) \
+  GNUNET_TIME_absolute_cmp ((t1).abs_time,op,(t2).abs_time)
+
+
+/**
+ * Compare two relative times.
+ *
+ * @param t1 first time
+ * @param op compare operator
+ * @param t2 second time
+ * @return true if @a t1 @a op @a t2
+ */
+#define GNUNET_TIME_relative_cmp(t1,op,t2) \
+  ((void) (1 op 2), (t1).rel_value_us op (t2).rel_value_us)
 
 
 /**
@@ -361,6 +481,30 @@ GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
                           struct GNUNET_TIME_Absolute t2);
 
 
+/**
+ * Return the maximum of two timestamps.
+ *
+ * @param t1 first timestamp
+ * @param t2 other timestamp
+ * @return timestamp that is smaller
+ */
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_max (struct GNUNET_TIME_Timestamp t1,
+                           struct GNUNET_TIME_Timestamp t2);
+
+
+/**
+ * Return the minimum of two timestamps.
+ *
+ * @param t1 first timestamp
+ * @param t2 other timestamp
+ * @return timestamp that is smaller
+ */
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1,
+                           struct GNUNET_TIME_Timestamp t2);
+
+
 /**
  * Given a timestamp in the future, how much time
  * remains until then?
@@ -529,6 +673,16 @@ struct GNUNET_TIME_AbsoluteNBO
 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a);
 
 
+/**
+ * Convert timestamp to network byte order.
+ *
+ * @param t time to convert
+ * @return converted time value
+ */
+struct GNUNET_TIME_TimestampNBO
+GNUNET_TIME_timestamp_hton (struct GNUNET_TIME_Timestamp t);
+
+
 /**
  * Convert milliseconds after the UNIX epoch to absolute time.
  *
@@ -557,6 +711,15 @@ bool
 GNUNET_TIME_absolute_is_past (struct GNUNET_TIME_Absolute abs);
 
 
+/**
+ * Test if @a abs is truly zero.
+ *
+ * @return true if it is.
+ */
+bool
+GNUNET_TIME_absolute_is_zero (struct GNUNET_TIME_Absolute abs);
+
+
 /**
  * Test if @a abs is truly in the future (excluding now).
  *
@@ -594,6 +757,15 @@ struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch);
 
 
+/**
+ * Convert seconds after the UNIX epoch to timestamp.
+ *
+ * @param s_after_epoch seconds after epoch to convert
+ * @return converted time value
+ */struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch);
+
+
 /**
  * Convert absolute time from network byte order.
  *
@@ -604,6 +776,16 @@ struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a);
 
 
+/**
+ * Convert timestamp from network byte order.
+ *
+ * @param tn time to convert
+ * @return converted time value
+ */
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_ntoh (struct GNUNET_TIME_TimestampNBO tn);
+
+
 /**
  * Set the timestamp offset for this instance.
  *
diff --git a/src/json/json_generator.c b/src/json/json_generator.c
index 0c513ca9d..eb275712c 100644
--- a/src/json/json_generator.c
+++ b/src/json/json_generator.c
@@ -27,14 +27,6 @@
 #include "gnunet_json_lib.h"
 
 
-/**
- * Convert binary data to a JSON string
- * with the base32crockford encoding.
- *
- * @param data binary data
- * @param size size of @a data in bytes
- * @return json string that encodes @a data
- */
 json_t *
 GNUNET_JSON_from_data (const void *data,
                        size_t size)
@@ -57,31 +49,22 @@ GNUNET_JSON_from_data (const void *data,
 }
 
 
-/**
- * Convert absolute timestamp to a json string.
- *
- * @param stamp the time stamp
- * @return a json string with the timestamp in @a stamp
- */
 json_t *
-GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp)
+GNUNET_JSON_from_timestamp (struct GNUNET_TIME_Timestamp stamp)
 {
   json_t *j;
 
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_TIME_round_abs (&stamp));
-
   j = json_object ();
   if (NULL == j)
   {
     GNUNET_break (0);
     return NULL;
   }
-  if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
+  if (GNUNET_TIME_absolute_is_never (stamp.abs_time))
   {
     if (0 !=
         json_object_set_new (j,
-                             "t_ms",
+                             "t_s",
                              json_string ("never")))
     {
       GNUNET_break (0);
@@ -90,11 +73,17 @@ GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute 
stamp)
     }
     return j;
   }
+  GNUNET_assert (
+    0 ==
+    (stamp.abs_time.abs_value_us
+     % GNUNET_TIME_UNIT_SECONDS.rel_value_us));
   if (0 !=
-      json_object_set_new (j,
-                           "t_ms",
-                           json_integer ((json_int_t) (stamp.abs_value_us
-                                                       / 1000LL))))
+      json_object_set_new (
+        j,
+        "t_s",
+        json_integer (
+          (json_int_t) (stamp.abs_time.abs_value_us
+                        / GNUNET_TIME_UNIT_SECONDS.rel_value_us))))
   {
     GNUNET_break (0);
     json_decref (j);
@@ -104,44 +93,29 @@ GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute 
stamp)
 }
 
 
-/**
- * Convert absolute timestamp to a json string.
- *
- * @param stamp the time stamp
- * @return a json string with the timestamp in @a stamp
- */
 json_t *
-GNUNET_JSON_from_time_abs_nbo (struct GNUNET_TIME_AbsoluteNBO stamp)
+GNUNET_JSON_from_timestamp_nbo (struct GNUNET_TIME_TimestampNBO stamp)
 {
-  return GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (stamp));
+  return GNUNET_JSON_from_timestamp (GNUNET_TIME_timestamp_ntoh (stamp));
 }
 
 
-/**
- * Convert relative timestamp to a json string.
- *
- * @param stamp the time stamp
- * @return a json string with the timestamp in @a stamp
- */
 json_t *
 GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
 {
   json_t *j;
 
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_TIME_round_rel (&stamp));
-
   j = json_object ();
   if (NULL == j)
   {
     GNUNET_break (0);
     return NULL;
   }
-  if (stamp.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+  if (GNUNET_TIME_relative_is_forever (stamp))
   {
     if (0 !=
         json_object_set_new (j,
-                             "d_ms",
+                             "d_us",
                              json_string ("forever")))
     {
       GNUNET_break (0);
@@ -150,11 +124,17 @@ GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative 
stamp)
     }
     return j;
   }
+  if (stamp.rel_value_us >= (1LLU << 53))
+  {
+    /* value is larger than allowed */
+    GNUNET_break (0);
+    return NULL;
+  }
   if (0 !=
-      json_object_set_new (j,
-                           "d_ms",
-                           json_integer ((json_int_t) (stamp.rel_value_us
-                                                       / 1000LL))))
+      json_object_set_new (
+        j,
+        "d_us",
+        json_integer ((json_int_t) stamp.rel_value_us)))
   {
     GNUNET_break (0);
     json_decref (j);
@@ -164,12 +144,6 @@ GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative 
stamp)
 }
 
 
-/**
- * Convert RSA public key to JSON.
- *
- * @param pk public key to convert
- * @return corresponding JSON encoding
- */
 json_t *
 GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk)
 {
@@ -186,12 +160,6 @@ GNUNET_JSON_from_rsa_public_key (const struct 
GNUNET_CRYPTO_RsaPublicKey *pk)
 }
 
 
-/**
- * Convert RSA signature to JSON.
- *
- * @param sig signature to convert
- * @return corresponding JSON encoding
- */
 json_t *
 GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig)
 {
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 3a11f205c..73f5fc00c 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -49,7 +49,7 @@ GNUNET_JSON_spec_end ()
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_fixed_data (void *cls,
                   json_t *root,
                   struct GNUNET_JSON_Specification *spec)
@@ -579,20 +579,20 @@ GNUNET_JSON_spec_int64 (const char *name,
 /* ************ GNUnet-specific parser specifications ******************* */
 
 /**
- * Parse given JSON object to absolute time.
+ * Parse given JSON object to a timestamp.
  *
  * @param cls closure, NULL
  * @param root the json object representing data
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
-parse_abs_time (void *cls,
-                json_t *root,
-                struct GNUNET_JSON_Specification *spec)
+static enum GNUNET_GenericReturnValue
+parse_timestamp (void *cls,
+                 json_t *root,
+                 struct GNUNET_JSON_Specification *spec)
 {
-  struct GNUNET_TIME_Absolute *abs = spec->ptr;
-  json_t *json_t_ms;
+  struct GNUNET_TIME_Timestamp *ts = spec->ptr;
+  json_t *json_t_s;
   unsigned long long int tval;
 
   if (! json_is_object (root))
@@ -600,14 +600,16 @@ parse_abs_time (void *cls,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  json_t_ms = json_object_get (root, "t_ms");
-  if (json_is_integer (json_t_ms))
+  json_t_s = json_object_get (root,
+                              "t_s");
+  if (json_is_integer (json_t_s))
   {
-    tval = json_integer_value (json_t_ms);
-    /* Time is in milliseconds in JSON, but in microseconds in 
GNUNET_TIME_Absolute */
-    abs->abs_value_us = tval * GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
-    if ((abs->abs_value_us)
-        / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us
+    tval = json_integer_value (json_t_s);
+    /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute 
*/
+    ts->abs_time.abs_value_us
+      = tval * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
+    if (ts->abs_time.abs_value_us
+        / GNUNET_TIME_UNIT_SECONDS.rel_value_us
         != tval)
     {
       /* Integer overflow */
@@ -616,14 +618,15 @@ parse_abs_time (void *cls,
     }
     return GNUNET_OK;
   }
-  if (json_is_string (json_t_ms))
+  if (json_is_string (json_t_s))
   {
     const char *val;
 
-    val = json_string_value (json_t_ms);
-    if ((0 == strcasecmp (val, "never")))
+    val = json_string_value (json_t_s);
+    if ((0 == strcasecmp (val,
+                          "never")))
     {
-      *abs = GNUNET_TIME_UNIT_FOREVER_ABS;
+      ts->abs_time = GNUNET_TIME_UNIT_FOREVER_ABS;
       return GNUNET_OK;
     }
     GNUNET_break_op (0);
@@ -635,17 +638,14 @@ parse_abs_time (void *cls,
 
 
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_absolute_time (const char *name,
-                                struct GNUNET_TIME_Absolute *at)
+GNUNET_JSON_spec_timestamp (const char *name,
+                            struct GNUNET_TIME_Timestamp *t)
 {
   struct GNUNET_JSON_Specification ret = {
-    .parser = &parse_abs_time,
-    .cleaner = NULL,
-    .cls = NULL,
+    .parser = &parse_timestamp,
     .field = name,
-    .ptr = at,
-    .ptr_size = sizeof(struct GNUNET_TIME_Absolute),
-    .size_ptr = NULL
+    .ptr = t,
+    .ptr_size = sizeof(struct GNUNET_TIME_Timestamp)
   };
 
   return ret;
@@ -660,40 +660,37 @@ GNUNET_JSON_spec_absolute_time (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
-parse_abs_time_nbo (void *cls,
-                    json_t *root,
-                    struct GNUNET_JSON_Specification *spec)
+static enum GNUNET_GenericReturnValue
+parse_timestamp_nbo (void *cls,
+                     json_t *root,
+                     struct GNUNET_JSON_Specification *spec)
 {
-  struct GNUNET_TIME_AbsoluteNBO *abs = spec->ptr;
-  struct GNUNET_TIME_Absolute a;
+  struct GNUNET_TIME_TimestampNBO *ts = spec->ptr;
+  struct GNUNET_TIME_Timestamp a;
   struct GNUNET_JSON_Specification ispec;
 
   ispec = *spec;
-  ispec.parser = &parse_abs_time;
+  ispec.parser = &parse_timestamp;
   ispec.ptr = &a;
   if (GNUNET_OK !=
-      parse_abs_time (NULL,
-                      root,
-                      &ispec))
+      parse_timestamp (NULL,
+                       root,
+                       &ispec))
     return GNUNET_SYSERR;
-  *abs = GNUNET_TIME_absolute_hton (a);
+  *ts = GNUNET_TIME_timestamp_hton (a);
   return GNUNET_OK;
 }
 
 
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_absolute_time_nbo (const char *name,
-                                    struct GNUNET_TIME_AbsoluteNBO *at)
+GNUNET_JSON_spec_timestamp_nbo (const char *name,
+                                struct GNUNET_TIME_TimestampNBO *at)
 {
   struct GNUNET_JSON_Specification ret = {
-    .parser = &parse_abs_time_nbo,
-    .cleaner = NULL,
-    .cls = NULL,
+    .parser = &parse_timestamp_nbo,
     .field = name,
     .ptr = at,
-    .ptr_size = sizeof(struct GNUNET_TIME_AbsoluteNBO),
-    .size_ptr = NULL
+    .ptr_size = sizeof(struct GNUNET_TIME_TimestampNBO)
   };
 
   return ret;
@@ -708,13 +705,13 @@ GNUNET_JSON_spec_absolute_time_nbo (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_rel_time (void *cls,
                 json_t *root,
                 struct GNUNET_JSON_Specification *spec)
 {
   struct GNUNET_TIME_Relative *rel = spec->ptr;
-  json_t *json_d_ms;
+  json_t *json_d_us;
   unsigned long long int tval;
 
   if (! json_is_object (root))
@@ -722,25 +719,27 @@ parse_rel_time (void *cls,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  json_d_ms = json_object_get (root, "d_ms");
-  if (json_is_integer (json_d_ms))
+  json_d_us = json_object_get (root,
+                               "d_us");
+  if (json_is_integer (json_d_us))
   {
-    tval = json_integer_value (json_d_ms);
-    /* Time is in milliseconds in JSON, but in microseconds in 
GNUNET_TIME_Absolute */
-    rel->rel_value_us = tval * 1000LL;
-    if ((rel->rel_value_us) / 1000LL != tval)
+    tval = json_integer_value (json_d_us);
+    if (tval >= (1LLU << 53))
     {
-      /* Integer overflow */
+      /* value is larger than allowed */
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
+    rel->rel_value_us = tval;
     return GNUNET_OK;
   }
-  if (json_is_string (json_d_ms))
+  if (json_is_string (json_d_us))
   {
     const char *val;
-    val = json_string_value (json_d_ms);
-    if ((0 == strcasecmp (val, "forever")))
+
+    val = json_string_value (json_d_us);
+    if ((0 == strcasecmp (val,
+                          "forever")))
     {
       *rel = GNUNET_TIME_UNIT_FOREVER_REL;
       return GNUNET_OK;
@@ -759,12 +758,9 @@ GNUNET_JSON_spec_relative_time (const char *name,
 {
   struct GNUNET_JSON_Specification ret = {
     .parser = &parse_rel_time,
-    .cleaner = NULL,
-    .cls = NULL,
     .field = name,
     .ptr = rt,
-    .ptr_size = sizeof(struct GNUNET_TIME_Relative),
-    .size_ptr = NULL
+    .ptr_size = sizeof(struct GNUNET_TIME_Relative)
   };
 
   return ret;
@@ -779,7 +775,7 @@ GNUNET_JSON_spec_relative_time (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_rsa_public_key (void *cls,
                       json_t *root,
                       struct GNUNET_JSON_Specification *spec)
@@ -864,7 +860,7 @@ GNUNET_JSON_spec_rsa_public_key (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_rsa_signature (void *cls,
                      json_t *root,
                      struct GNUNET_JSON_Specification *spec)
@@ -952,7 +948,7 @@ GNUNET_JSON_spec_rsa_signature (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_boolean (void *cls,
                json_t *root,
                struct GNUNET_JSON_Specification *spec)
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index 92f8b4535..296f56104 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -245,16 +245,16 @@ GNUNET_JSON_pack_data_varsize (const char *name,
 
 
 struct GNUNET_JSON_PackSpec
-GNUNET_JSON_pack_time_abs (const char *name,
-                           struct GNUNET_TIME_Absolute at)
+GNUNET_JSON_pack_timestamp (const char *name,
+                            struct GNUNET_TIME_Timestamp t)
 {
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name
   };
 
-  if (0 != at.abs_value_us)
+  if (! GNUNET_TIME_absolute_is_zero (t.abs_time))
   {
-    ps.object = GNUNET_JSON_from_time_abs (at);
+    ps.object = GNUNET_JSON_from_timestamp (t);
     GNUNET_assert (NULL != ps.object);
   }
   else
@@ -266,11 +266,11 @@ GNUNET_JSON_pack_time_abs (const char *name,
 
 
 struct GNUNET_JSON_PackSpec
-GNUNET_JSON_pack_time_abs_nbo (const char *name,
-                               struct GNUNET_TIME_AbsoluteNBO at)
+GNUNET_JSON_pack_timestamp_nbo (const char *name,
+                                struct GNUNET_TIME_TimestampNBO at)
 {
-  return GNUNET_JSON_pack_time_abs (name,
-                                    GNUNET_TIME_absolute_ntoh (at));
+  return GNUNET_JSON_pack_timestamp (name,
+                                     GNUNET_TIME_timestamp_ntoh (at));
 }
 
 
diff --git a/src/json/test_json.c b/src/json/test_json.c
index 4485a37a4..7e9025b5b 100644
--- a/src/json/test_json.c
+++ b/src/json/test_json.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   (C) 2015, 2016 GNUnet e.V.
+   (C) 2015, 2016, 2021 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -34,33 +34,45 @@
  * @return 0 on success
  */
 static int
-test_abs_time ()
+test_timestamp (void)
 {
   json_t *j;
   struct GNUNET_TIME_Absolute a1;
-  struct GNUNET_TIME_Absolute a2;
-  struct GNUNET_JSON_Specification s1[] = { GNUNET_JSON_spec_absolute_time (
-                                              NULL,
-                                              &a2),
-                                            GNUNET_JSON_spec_end () };
-  struct GNUNET_JSON_Specification s2[] = { GNUNET_JSON_spec_absolute_time (
-                                              NULL,
-                                              &a2),
-                                            GNUNET_JSON_spec_end () };
+  struct GNUNET_TIME_Timestamp t1;
+  struct GNUNET_TIME_Timestamp t2;
+  struct GNUNET_JSON_Specification s1[] = {
+    GNUNET_JSON_spec_timestamp (NULL,
+                                &t2),
+    GNUNET_JSON_spec_end ()
+  };
+  struct GNUNET_JSON_Specification s2[] = {
+    GNUNET_JSON_spec_timestamp (NULL,
+                                &t2),
+    GNUNET_JSON_spec_end ()
+  };
 
   a1 = GNUNET_TIME_absolute_get ();
-  GNUNET_TIME_round_abs (&a1);
-  j = GNUNET_JSON_from_time_abs (a1);
+  GNUNET_TIME_absolute_to_timestamp (a1,
+                                     &t1);
+  j = GNUNET_JSON_from_timestamp (t1);
   GNUNET_assert (NULL != j);
-  GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, s1, NULL, NULL));
-  GNUNET_assert (a1.abs_value_us == a2.abs_value_us);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (j,
+                                    s1,
+                                    NULL,
+                                    NULL));
+  GNUNET_assert (GNUNET_TIME_timestamp_cmp (t1, ==, t2));
   json_decref (j);
 
   a1 = GNUNET_TIME_UNIT_FOREVER_ABS;
-  j = GNUNET_JSON_from_time_abs (a1);
+  j = GNUNET_JSON_from_timestamp (t1);
   GNUNET_assert (NULL != j);
-  GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, s2, NULL, NULL));
-  GNUNET_assert (a1.abs_value_us == a2.abs_value_us);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (j,
+                                    s2,
+                                    NULL,
+                                    NULL));
+  GNUNET_assert (GNUNET_TIME_timestamp_cmp (t1, ==, t2));
   json_decref (j);
   return 0;
 }
@@ -72,19 +84,21 @@ test_abs_time ()
  * @return 0 on success
  */
 static int
-test_rel_time ()
+test_rel_time (void)
 {
   json_t *j;
   struct GNUNET_TIME_Relative r1;
   struct GNUNET_TIME_Relative r2;
-  struct GNUNET_JSON_Specification s1[] = { GNUNET_JSON_spec_relative_time (
-                                              NULL,
-                                              &r2),
-                                            GNUNET_JSON_spec_end () };
-  struct GNUNET_JSON_Specification s2[] = { GNUNET_JSON_spec_relative_time (
-                                              NULL,
-                                              &r2),
-                                            GNUNET_JSON_spec_end () };
+  struct GNUNET_JSON_Specification s1[] = {
+    GNUNET_JSON_spec_relative_time (NULL,
+                                    &r2),
+    GNUNET_JSON_spec_end ()
+  };
+  struct GNUNET_JSON_Specification s2[] = {
+    GNUNET_JSON_spec_relative_time (NULL,
+                                    &r2),
+    GNUNET_JSON_spec_end ()
+  };
 
   r1 = GNUNET_TIME_UNIT_SECONDS;
   j = GNUNET_JSON_from_time_rel (r1);
@@ -211,7 +225,7 @@ int
 main (int argc, const char *const argv[])
 {
   GNUNET_log_setup ("test-json", "WARNING", NULL);
-  if (0 != test_abs_time ())
+  if (0 != test_timestamp ())
     return 1;
   if (0 != test_rel_time ())
     return 1;
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index 78c324512..f5b4f38a2 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -70,7 +70,8 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_null (void)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_null, NULL, NULL, 0, 1
+    .conv = &qconv_null,
+    .num_params = 1
   };
 
   return res;
@@ -192,7 +193,10 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_uint16 (const uint16_t *x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_uint16, NULL, x, sizeof(*x), 1
+    .conv = &qconv_uint16,
+    .data = x,
+    .size = sizeof(*x),
+    .num_params = 1
   };
 
   return res;
@@ -246,7 +250,10 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_uint32 (const uint32_t *x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_uint32, NULL, x, sizeof(*x), 1
+    .conv = &qconv_uint32,
+    .data = x,
+    .size = sizeof(*x),
+    .num_params = 1
   };
 
   return res;
@@ -300,7 +307,10 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_uint64 (const uint64_t *x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_uint64, NULL, x, sizeof(*x), 1
+    .conv = &qconv_uint64,
+    .data = x,
+    .size = sizeof(*x),
+    .num_params = 1
   };
 
   return res;
@@ -350,11 +360,13 @@ qconv_rsa_public_key (void *cls,
 
 
 struct GNUNET_PQ_QueryParam
-GNUNET_PQ_query_param_rsa_public_key (const struct
-                                      GNUNET_CRYPTO_RsaPublicKey *x)
+GNUNET_PQ_query_param_rsa_public_key (
+  const struct GNUNET_CRYPTO_RsaPublicKey *x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_rsa_public_key, NULL, (x), 0, 1
+    .conv = &qconv_rsa_public_key,
+    .data = x,
+    .num_params = 1
   };
 
   return res;
@@ -407,7 +419,9 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature 
*x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_rsa_signature, NULL, (x), 0, 1
+    .conv = &qconv_rsa_signature,
+    .data = x,
+    .num_params = 1
   };
 
   return res;
@@ -463,7 +477,10 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_rel_time, NULL, x, sizeof(*x), 1
+    .conv = &qconv_rel_time,
+    .data = x,
+    .size = sizeof(*x),
+    .num_params = 1
   };
 
   return res;
@@ -519,7 +536,10 @@ struct GNUNET_PQ_QueryParam
 GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
 {
   struct GNUNET_PQ_QueryParam res = {
-    &qconv_abs_time, NULL, x, sizeof(*x), 1
+    .conv = &qconv_abs_time,
+    .data = x,
+    .size = sizeof(*x),
+    .num_params = 1
   };
 
   return res;
@@ -534,4 +554,71 @@ GNUNET_PQ_query_param_absolute_time_nbo (
 }
 
 
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
+qconv_timestamp (void *cls,
+                 const void *data,
+                 size_t data_len,
+                 void *param_values[],
+                 int param_lengths[],
+                 int param_formats[],
+                 unsigned int param_length,
+                 void *scratch[],
+                 unsigned int scratch_length)
+{
+  const struct GNUNET_TIME_Timestamp *u = data;
+  struct GNUNET_TIME_Absolute abs;
+  uint64_t *u_nbo;
+
+  GNUNET_break (NULL == cls);
+  if (1 != param_length)
+    return -1;
+  abs = u->abs_time;
+  if (abs.abs_value_us > INT64_MAX)
+    abs.abs_value_us = INT64_MAX;
+  u_nbo = GNUNET_new (uint64_t);
+  scratch[0] = u_nbo;
+  *u_nbo = GNUNET_htonll (abs.abs_value_us);
+  param_values[0] = (void *) u_nbo;
+  param_lengths[0] = sizeof(uint64_t);
+  param_formats[0] = 1;
+  return 1;
+}
+
+
+struct GNUNET_PQ_QueryParam
+GNUNET_PQ_query_param_timestamp (const struct GNUNET_TIME_Timestamp *x)
+{
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_timestamp,
+    .data = x,
+    .size = sizeof(*x),
+    .num_params = 1
+  };
+
+  return res;
+}
+
+
+struct GNUNET_PQ_QueryParam
+GNUNET_PQ_query_param_timestamp_nbo (
+  const struct GNUNET_TIME_TimestampNBO *x)
+{
+  return GNUNET_PQ_query_param_absolute_time_nbo (&x->abs_time_nbo);
+}
+
+
 /* end of pq_query_helper.c */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index 4057772ec..be7c85ce9 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -743,6 +743,148 @@ GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
 }
 
 
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param int row to extract data from
+ * @param fname name (or prefix) of the fields to extract from
+ * @param[in,out] dst_size where to store size of result, may be NULL
+ * @param[out] dst where to store the result
+ * @return
+ *   #GNUNET_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static enum GNUNET_GenericReturnValue
+extract_timestamp (void *cls,
+                   PGresult *result,
+                   int row,
+                   const char *fname,
+                   size_t *dst_size,
+                   void *dst)
+{
+  struct GNUNET_TIME_Timestamp *udst = dst;
+  struct GNUNET_TIME_Absolute abs;
+  const int64_t *res;
+  int fnum;
+
+  (void) cls;
+  fnum = PQfnumber (result,
+                    fname);
+  if (fnum < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (PQgetisnull (result,
+                   row,
+                   fnum))
+    return GNUNET_NO;
+  GNUNET_assert (NULL != dst);
+  if (sizeof(struct GNUNET_TIME_Absolute) != *dst_size)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (sizeof(int64_t) !=
+      PQgetlength (result,
+                   row,
+                   fnum))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  res = (int64_t *) PQgetvalue (result,
+                                row,
+                                fnum);
+  if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
+  {
+    abs = GNUNET_TIME_UNIT_FOREVER_ABS;
+  }
+  else
+  {
+    abs.abs_value_us = GNUNET_ntohll ((uint64_t) *res);
+    if (0 != abs.abs_value_us % GNUNET_TIME_UNIT_SECONDS.rel_value_us)
+    {
+      /* timestamps must be multiple of seconds! */
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+  }
+  udst->abs_time = abs;
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_PQ_ResultSpec
+GNUNET_PQ_result_spec_timestamp (const char *name,
+                                 struct GNUNET_TIME_Timestamp *at)
+{
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = &extract_timestamp,
+    .dst = (void *) at,
+    .dst_size = sizeof(*at),
+    .fname = name
+  };
+
+  return res;
+}
+
+
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param int row to extract data from
+ * @param fname name (or prefix) of the fields to extract from
+ * @param[in,out] dst_size where to store size of result, may be NULL
+ * @param[out] dst where to store the result
+ * @return
+ *   #GNUNET_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static enum GNUNET_GenericReturnValue
+extract_timestamp_nbo (void *cls,
+                       PGresult *result,
+                       int row,
+                       const char *fname,
+                       size_t *dst_size,
+                       void *dst)
+{
+  struct GNUNET_TIME_TimestampNBO *udst = dst;
+  struct GNUNET_TIME_Timestamp t;
+  enum GNUNET_GenericReturnValue r;
+
+  r = extract_timestamp (&t,
+                         result,
+                         row,
+                         fname,
+                         dst_size,
+                         dst);
+  if (GNUNET_OK != r)
+    return r;
+  *udst = GNUNET_TIME_timestamp_hton (t);
+  return r;
+}
+
+
+struct GNUNET_PQ_ResultSpec
+GNUNET_PQ_result_spec_timestamp_nbo (const char *name,
+                                     struct GNUNET_TIME_TimestampNBO *at)
+{
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = &extract_timestamp_nbo,
+    .dst = (void *) at,
+    .dst_size = sizeof(*at),
+    .fname = name
+  };
+
+  return res;
+}
+
+
 /**
  * Extract data from a Postgres database @a result at row @a row.
  *
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 9fda40f51..406d42b1e 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -144,7 +144,7 @@ libgnunetutil_la_LIBADD = \
 
 libgnunetutil_la_LDFLAGS = \
   $(GN_LIB_LDFLAGS) \
-  -version-info 14:0:0
+  -version-info 15:0:0
 
 GNUNET_ECC = gnunet-ecc
 GNUNET_SCRYPT = gnunet-scrypt
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c
index 592875531..917aa440b 100644
--- a/src/util/getopt_helpers.c
+++ b/src/util/getopt_helpers.c
@@ -38,7 +38,7 @@
  * @param value not used (NULL)
  * @return #GNUNET_NO (do not continue, not an error)
  */
-static int
+static enum GNUNET_GenericReturnValue
 print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
                void *scls,
                const char *option,
@@ -53,12 +53,6 @@ print_version (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Define the option to print the version of
- * the application (-v option)
- *
- * @param version string with the version number
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_version (const char *version)
 {
@@ -90,7 +84,7 @@ GNUNET_GETOPT_option_version (const char *version)
  * @param value not used (NULL)
  * @return #GNUNET_NO (do not continue, not an error)
  */
-static int
+static enum GNUNET_GenericReturnValue
 format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
              void *scls,
              const char *option,
@@ -192,12 +186,6 @@ OUTER:
 }
 
 
-/**
- * Defining the option to print the command line
- * help text (-h option).
- *
- * @param about string with brief description of the application
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_help (const char *about)
 {
@@ -229,7 +217,7 @@ GNUNET_GETOPT_option_help (const char *about)
  * @param value not used (NULL)
  * @return #GNUNET_OK
  */
-static int
+static enum GNUNET_GenericReturnValue
 increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
                  void *scls,
                  const char *option,
@@ -245,15 +233,6 @@ increment_value (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Increment @a val each time the option flag is given by one.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val increment by 1 each time the option is present
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_increment_uint (char shortName,
                                      const char *name,
@@ -272,12 +251,6 @@ GNUNET_GETOPT_option_increment_uint (char shortName,
 }
 
 
-/**
- * Define the '-V' verbosity option.  Using the option more
- * than once increments @a level each time.
- *
- * @param[out] level set to the verbosity level
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_verbose (unsigned int *level)
 {
@@ -308,7 +281,7 @@ GNUNET_GETOPT_option_verbose (unsigned int *level)
  * @param value not used (NULL)
  * @return #GNUNET_OK
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
          void *scls,
          const char *option,
@@ -324,16 +297,6 @@ set_one (struct GNUNET_GETOPT_CommandLineProcessorContext 
*ctx,
 }
 
 
-/**
- * Allow user to specify a flag (which internally means setting
- * an integer to 1/#GNUNET_YES/#GNUNET_OK.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val set to 1 if the option is present
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_flag (char shortName,
                            const char *name,
@@ -366,7 +329,7 @@ GNUNET_GETOPT_option_flag (char shortName,
  * @param value actual value of the option (a string)
  * @return #GNUNET_OK
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
             void *scls,
             const char *option,
@@ -383,15 +346,6 @@ set_string (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify a string.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] str set to the string
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_string (char shortName,
                              const char *name,
@@ -413,12 +367,6 @@ GNUNET_GETOPT_option_string (char shortName,
 }
 
 
-/**
- * Define the '-L' log level option.  Note that we do not check
- * that the log level is valid here.
- *
- * @param[out] level set to the log level
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_loglevel (char **level)
 {
@@ -447,7 +395,7 @@ GNUNET_GETOPT_option_loglevel (char **level)
  * @param value actual value of the option (a string)
  * @return #GNUNET_OK
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
               void *scls,
               const char *option,
@@ -464,15 +412,6 @@ set_filename (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify a filename (automatically path expanded).
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] str set to the string
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_filename (char shortName,
                                const char *name,
@@ -494,11 +433,6 @@ GNUNET_GETOPT_option_filename (char shortName,
 }
 
 
-/**
- * Allow user to specify log file name (-l option)
- *
- * @param[out] logfn set to the name of the logfile
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_logfile (char **logfn)
 {
@@ -517,11 +451,6 @@ GNUNET_GETOPT_option_logfile (char **logfn)
 }
 
 
-/**
- * Allow user to specify configuration file name (-c option)
- *
- * @param[out] fn set to the name of the configuration file
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_cfgfile (char **fn)
 {
@@ -552,7 +481,7 @@ GNUNET_GETOPT_option_cfgfile (char **fn)
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
            void *scls,
            const char *option,
@@ -573,15 +502,6 @@ set_ulong (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify an `unsigned long long`
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val set to the value specified at the command line
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_ulong (char shortName,
                             const char *name,
@@ -616,7 +536,7 @@ GNUNET_GETOPT_option_ulong (char shortName,
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_timetravel_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
                      void *scls,
                      const char *option,
@@ -664,15 +584,6 @@ set_timetravel_time (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify a `long long` with an offset to add to the current
- * system time to construct the time seen by the application. Used for
- * debugging / testing.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param[out] val set to the time specified at the command line
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_timetravel (char shortName,
                                  const char *name)
@@ -684,8 +595,7 @@ GNUNET_GETOPT_option_timetravel (char shortName,
     .description = _ (
       "modify system time by given offset (for debugging/testing only)"),
     .require_argument = 1,
-    .processor =
-      &set_timetravel_time
+    .processor = &set_timetravel_time
   };
 
   return clo;
@@ -705,7 +615,7 @@ GNUNET_GETOPT_option_timetravel (char shortName,
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
                    void *scls,
                    const char *option,
@@ -725,16 +635,6 @@ set_relative_time (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify a `struct GNUNET_TIME_Relative`
- * (using human-readable "fancy" time).
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val set to the time specified at the command line
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_relative_time (char shortName,
                                     const char *name,
@@ -748,8 +648,7 @@ GNUNET_GETOPT_option_relative_time (char shortName,
     .argumentHelp = argumentHelp,
     .description = description,
     .require_argument = 1,
-    .processor =
-      &set_relative_time,
+    .processor = &set_relative_time,
     .scls = (void *) val
   };
 
@@ -770,7 +669,7 @@ GNUNET_GETOPT_option_relative_time (char shortName,
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
                    void *scls,
                    const char *option,
@@ -790,16 +689,6 @@ set_absolute_time (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify a `struct GNUNET_TIME_Absolute`
- * (using human-readable "fancy" time).
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val set to the time specified at the command line
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_absolute_time (char shortName,
                                     const char *name,
@@ -813,8 +702,71 @@ GNUNET_GETOPT_option_absolute_time (char shortName,
     .argumentHelp = argumentHelp,
     .description = description,
     .require_argument = 1,
-    .processor =
-      &set_absolute_time,
+    .processor = &set_absolute_time,
+    .scls = (void *) val
+  };
+
+  return clo;
+}
+
+
+/**
+ * Set an option of type 'struct GNUNET_TIME_Timestamp' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type.  It should be followed by a pointer to a value of
+ * type 'struct GNUNET_TIME_Absolute'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the `struct 
GNUNET_TIME_Absolute`)
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static enum GNUNET_GenericReturnValue
+set_timestamp (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+               void *scls,
+               const char *option,
+               const char *value)
+{
+  struct GNUNET_TIME_Timestamp *t = scls;
+  struct GNUNET_TIME_Absolute abs;
+
+  (void) ctx;
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_fancy_time_to_absolute (value,
+                                             &abs))
+  {
+    fprintf (stderr,
+             _ ("You must pass a timestamp to the `%s' option.\n"),
+             option);
+    return GNUNET_SYSERR;
+  }
+  if (0 != abs.abs_value_us % GNUNET_TIME_UNIT_SECONDS.rel_value_us)
+  {
+    fprintf (stderr,
+             _ ("The maximum precision allowed for timestamps is seconds.\n"));
+    return GNUNET_SYSERR;
+  }
+  t->abs_time = abs;
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_option_timestamp (char shortName,
+                                const char *name,
+                                const char *argumentHelp,
+                                const char *description,
+                                struct GNUNET_TIME_Timestamp *val)
+{
+  struct GNUNET_GETOPT_CommandLineOption clo = {
+    .shortName = shortName,
+    .name = name,
+    .argumentHelp = argumentHelp,
+    .description = description,
+    .require_argument = 1,
+    .processor = &set_timestamp,
     .scls = (void *) val
   };
 
@@ -835,7 +787,7 @@ GNUNET_GETOPT_option_absolute_time (char shortName,
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
           void *scls,
           const char *option,
@@ -864,15 +816,6 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext 
*ctx,
 }
 
 
-/**
- * Allow user to specify an unsigned integer.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val set to the value specified at the command line
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_uint (char shortName,
                            const char *name,
@@ -907,7 +850,7 @@ GNUNET_GETOPT_option_uint (char shortName,
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
             void *scls,
             const char *option,
@@ -938,15 +881,6 @@ set_uint16 (struct 
GNUNET_GETOPT_CommandLineProcessorContext *ctx,
 }
 
 
-/**
- * Allow user to specify an uint16_t.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val set to the value specified at the command line
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_uint16 (char shortName,
                              const char *name,
@@ -998,7 +932,7 @@ struct Base32Context
  * @param value actual value of the option as a string.
  * @return #GNUNET_OK if parsing the value worked
  */
-static int
+static enum GNUNET_GenericReturnValue
 set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
             void *scls,
             const char *option,
@@ -1036,17 +970,6 @@ free_bc (void *cls)
 }
 
 
-/**
- * Allow user to specify a binary value using Crockford
- * Base32 encoding.
- *
- * @param shortName short name of the option
- * @param name long name of the option
- * @param argumentHelp help text for the option argument
- * @param description long help text for the option
- * @param[out] val binary value decoded from Crockford Base32-encoded argument
- * @param val_size size of @a val in bytes
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_base32_fixed_size (char shortName,
                                         const char *name,
@@ -1073,12 +996,6 @@ GNUNET_GETOPT_option_base32_fixed_size (char shortName,
 }
 
 
-/**
- * Make the given option mandatory.
- *
- * @param opt option to modify
- * @return @a opt with the mandatory flag set.
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
 {
@@ -1087,12 +1004,6 @@ GNUNET_GETOPT_option_mandatory (struct 
GNUNET_GETOPT_CommandLineOption opt)
 }
 
 
-/**
- * Make the given option mutually exclusive with other options.
- *
- * @param opt option to modify
- * @return @a opt with the exclusive flag set.
- */
 struct GNUNET_GETOPT_CommandLineOption
 GNUNET_GETOPT_option_exclusive (struct GNUNET_GETOPT_CommandLineOption opt)
 {
diff --git a/src/util/strings.c b/src/util/strings.c
index 673915888..db672da87 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -201,7 +201,7 @@ struct ConversionTable
  * @param output where to store the result
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static int
+static enum GNUNET_GenericReturnValue
 convert_with_table (const char *input,
                     const struct ConversionTable *table,
                     unsigned long long *output)
@@ -256,7 +256,7 @@ convert_with_table (const char *input,
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
                                     unsigned long long *size)
 {
@@ -280,7 +280,7 @@ GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
                                        struct GNUNET_TIME_Relative *rtime)
 {
@@ -322,7 +322,7 @@ GNUNET_STRINGS_fancy_time_to_relative (const char 
*fancy_time,
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
                                        struct GNUNET_TIME_Absolute *atime)
 {
@@ -354,6 +354,15 @@ GNUNET_STRINGS_fancy_time_to_absolute (const char 
*fancy_time,
 }
 
 
+enum GNUNET_GenericReturnValue
+GNUNET_STRINGS_fancy_time_to_timestamp (const char *fancy_time,
+                                        struct GNUNET_TIME_Timestamp *atime)
+{
+  return GNUNET_STRINGS_fancy_time_to_absolute (fancy_time,
+                                                &atime->abs_time);
+}
+
+
 char *
 GNUNET_STRINGS_conv (const char *input,
                      size_t len,
@@ -607,7 +616,7 @@ GNUNET_STRINGS_absolute_time_to_string (struct 
GNUNET_TIME_Absolute t)
   time_t tt;
   struct tm *tp;
 
-  if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
+  if (GNUNET_TIME_absolute_is_never (t))
     return "end of time";
   tt = t.abs_value_us / 1000LL / 1000LL;
   tp = localtime (&tt);
@@ -616,7 +625,8 @@ GNUNET_STRINGS_absolute_time_to_string (struct 
GNUNET_TIME_Absolute t)
    * As for msvcrt, use the wide variant, which always returns utf16
    * (otherwise we'd have to detect current codepage or use W32API character
    * set conversion routines to convert to UTF8).
-   */strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
+   */
+  strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
 
   return buf;
 }
diff --git a/src/util/time.c b/src/util/time.c
index 144e1b401..83b39b4e8 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -58,27 +58,35 @@ GNUNET_TIME_get_offset ()
 }
 
 
-int
-GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at)
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at)
 {
-  if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
-    return GNUNET_OK;
-  if (0 == at->abs_value_us % 1000000)
-    return GNUNET_OK;
-  at->abs_value_us -= at->abs_value_us % 1000000;
-  return GNUNET_NO;
+  struct GNUNET_TIME_Timestamp ts;
+
+  if (GNUNET_TIME_absolute_is_never (at))
+    return GNUNET_TIME_UNIT_FOREVER_TS;
+  ts.abs_time.abs_value_us = at.abs_value_us - at.abs_value_us % 1000000;
+  return ts;
+}
+
+
+struct GNUNET_TIME_TimestampNBO
+GNUNET_TIME_timestamp_hton (struct GNUNET_TIME_Timestamp t)
+{
+  struct GNUNET_TIME_TimestampNBO tn;
+
+  tn.abs_time_nbo = GNUNET_TIME_absolute_hton (t.abs_time);
+  return tn;
 }
 
 
-int
-GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt)
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_ntoh (struct GNUNET_TIME_TimestampNBO tn)
 {
-  if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
-    return GNUNET_OK;
-  if (0 == rt->rel_value_us % 1000000)
-    return GNUNET_OK;
-  rt->rel_value_us -= rt->rel_value_us % 1000000;
-  return GNUNET_NO;
+  struct GNUNET_TIME_Timestamp t;
+
+  t.abs_time = GNUNET_TIME_absolute_ntoh (tn.abs_time_nbo);
+  return t;
 }
 
 
@@ -96,6 +104,14 @@ GNUNET_TIME_absolute_get ()
 }
 
 
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_get ()
+{
+  return GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_get ());
+}
+
+
 struct GNUNET_TIME_Relative
 GNUNET_TIME_relative_get_zero_ ()
 {
@@ -177,12 +193,114 @@ GNUNET_TIME_absolute_get_forever_ ()
 }
 
 
+const char *
+GNUNET_TIME_timestamp2s (struct GNUNET_TIME_Timestamp ts)
+{
+  static GNUNET_THREAD_LOCAL char buf[255];
+  time_t tt;
+  struct tm *tp;
+
+  if (GNUNET_TIME_absolute_is_never (ts.abs_time))
+    return "end of time";
+  tt = ts.abs_time.abs_value_us / 1000LL / 1000LL;
+  tp = localtime (&tt);
+  /* This is hacky, but i don't know a way to detect libc character encoding.
+   * Just expect utf8 from glibc these days.
+   * As for msvcrt, use the wide variant, which always returns utf16
+   * (otherwise we'd have to detect current codepage or use W32API character
+   * set conversion routines to convert to UTF8).
+   */
+  strftime (buf,
+            sizeof(buf),
+            "%a %b %d %H:%M:%S %Y",
+            tp);
+  return buf;
+}
+
+
+const char *
+GNUNET_TIME_absolute2s (struct GNUNET_TIME_Absolute t)
+{
+  static GNUNET_THREAD_LOCAL char buf[255];
+  time_t tt;
+  struct tm *tp;
+
+  if (GNUNET_TIME_absolute_is_never (t))
+    return "end of time";
+  tt = t.abs_value_us / 1000LL / 1000LL;
+  tp = localtime (&tt);
+  /* This is hacky, but i don't know a way to detect libc character encoding.
+   * Just expect utf8 from glibc these days.
+   * As for msvcrt, use the wide variant, which always returns utf16
+   * (otherwise we'd have to detect current codepage or use W32API character
+   * set conversion routines to convert to UTF8).
+   */
+  strftime (buf,
+            sizeof(buf),
+            "%a %b %d %H:%M:%S %Y",
+            tp);
+  return buf;
+}
+
+
+const char *
+GNUNET_TIME_relative2s (struct GNUNET_TIME_Relative delta,
+                        bool do_round)
+{
+  static GNUNET_THREAD_LOCAL char buf[128];
+  const char *unit = /* time unit */ "µs";
+  uint64_t dval = delta.rel_value_us;
+
+  if (GNUNET_TIME_relative_is_forever (delta))
+    return "forever";
+  if (0 == delta.rel_value_us)
+    return "0 ms";
+  if ( ((GNUNET_YES == do_round) &&
+        (dval > 5 * 1000)) ||
+       (0 == (dval % 1000)))
+  {
+    dval = dval / 1000;
+    unit = /* time unit */ "ms";
+    if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 
1000)))
+    {
+      dval = dval / 1000;
+      unit = /* time unit */ "s";
+      if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
+      {
+        dval = dval / 60;
+        unit = /* time unit */ "m";
+        if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 
60)))
+        {
+          dval = dval / 60;
+          unit = /* time unit */ "h";
+          if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
+              (0 == (dval % 24)))
+          {
+            dval = dval / 24;
+            if (1 == dval)
+              unit = /* time unit */ "day";
+            else
+              unit = /* time unit */ "days";
+          }
+        }
+      }
+    }
+  }
+  GNUNET_snprintf (buf,
+                   sizeof(buf),
+                   "%llu %s",
+                   (unsigned long long) dval,
+                   unit);
+  return buf;
+}
+
+
 struct GNUNET_TIME_Absolute
 GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
 {
   struct GNUNET_TIME_Absolute ret;
 
-  if (rel.rel_value_us == UINT64_MAX)
+  if (GNUNET_TIME_relative_is_forever (rel))
     return GNUNET_TIME_UNIT_FOREVER_ABS;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
@@ -196,6 +314,14 @@ GNUNET_TIME_relative_to_absolute (struct 
GNUNET_TIME_Relative rel)
 }
 
 
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_relative_to_timestamp (struct GNUNET_TIME_Relative rel)
+{
+  return GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_relative_to_absolute (rel));
+}
+
+
 struct GNUNET_TIME_Relative
 GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
                           struct GNUNET_TIME_Relative t2)
@@ -228,12 +354,28 @@ GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
 }
 
 
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_max (struct GNUNET_TIME_Timestamp t1,
+                           struct GNUNET_TIME_Timestamp t2)
+{
+  return (t1.abs_time.abs_value_us > t2.abs_time.abs_value_us) ? t1 : t2;
+}
+
+
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1,
+                           struct GNUNET_TIME_Timestamp t2)
+{
+  return (t1.abs_time.abs_value_us < t2.abs_time.abs_value_us) ? t1 : t2;
+}
+
+
 struct GNUNET_TIME_Relative
 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
 {
   struct GNUNET_TIME_Relative ret;
 
-  if (future.abs_value_us == UINT64_MAX)
+  if (GNUNET_TIME_absolute_is_never (future))
     return GNUNET_TIME_UNIT_FOREVER_REL;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
@@ -250,7 +392,7 @@ GNUNET_TIME_absolute_get_difference (struct 
GNUNET_TIME_Absolute start,
 {
   struct GNUNET_TIME_Relative ret;
 
-  if (end.abs_value_us == UINT64_MAX)
+  if (GNUNET_TIME_absolute_is_never (end))
     return GNUNET_TIME_UNIT_FOREVER_REL;
   if (end.abs_value_us < start.abs_value_us)
     return GNUNET_TIME_UNIT_ZERO;
@@ -279,8 +421,8 @@ GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
 {
   struct GNUNET_TIME_Absolute ret;
 
-  if ((start.abs_value_us == UINT64_MAX) ||
-      (duration.rel_value_us == UINT64_MAX))
+  if (GNUNET_TIME_absolute_is_never (start) ||
+      GNUNET_TIME_relative_is_forever (duration))
     return GNUNET_TIME_UNIT_FOREVER_ABS;
   if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
   {
@@ -300,7 +442,7 @@ GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute 
start,
 
   if (start.abs_value_us <= duration.rel_value_us)
     return GNUNET_TIME_UNIT_ZERO_ABS;
-  if (start.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
+  if (GNUNET_TIME_absolute_is_never (start))
     return GNUNET_TIME_UNIT_FOREVER_ABS;
   ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
   return ret;
@@ -315,7 +457,7 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative 
rel,
 
   if (0 == factor)
     return GNUNET_TIME_UNIT_ZERO;
-  if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+  if (GNUNET_TIME_relative_is_forever (rel))
     return GNUNET_TIME_UNIT_FOREVER_REL;
   ret.rel_value_us = rel.rel_value_us * factor;
   if (ret.rel_value_us / factor != rel.rel_value_us)
@@ -328,7 +470,8 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative 
rel,
 
 
 struct GNUNET_TIME_Relative
-relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor)
+relative_multiply_double (struct GNUNET_TIME_Relative rel,
+                          double factor)
 {
   struct GNUNET_TIME_Relative out;
   double m;
@@ -337,7 +480,7 @@ relative_multiply_double (struct GNUNET_TIME_Relative rel, 
double factor)
 
   if (0 == factor)
     return GNUNET_TIME_UNIT_ZERO;
-  if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+  if (GNUNET_TIME_relative_is_forever (rel))
     return GNUNET_TIME_UNIT_FOREVER_REL;
 
   m = ((double) rel.rel_value_us) * factor;
@@ -361,7 +504,7 @@ GNUNET_TIME_relative_saturating_multiply (struct 
GNUNET_TIME_Relative rel,
 
   if (0 == factor)
     return GNUNET_TIME_UNIT_ZERO;
-  if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+  if (GNUNET_TIME_relative_is_forever (rel))
     return GNUNET_TIME_UNIT_FOREVER_REL;
   ret.rel_value_us = rel.rel_value_us * factor;
   if (ret.rel_value_us / factor != rel.rel_value_us)
@@ -379,7 +522,7 @@ GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative 
rel,
   struct GNUNET_TIME_Relative ret;
 
   if ((0 == factor) ||
-      (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
+      (GNUNET_TIME_relative_is_forever (rel)))
     return GNUNET_TIME_UNIT_FOREVER_REL;
   ret.rel_value_us = rel.rel_value_us / factor;
   return ret;
@@ -538,6 +681,20 @@ GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch)
 }
 
 
+struct GNUNET_TIME_Timestamp
+GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch)
+{
+  struct GNUNET_TIME_Timestamp ret;
+
+  ret.abs_time.abs_value_us
+    = GNUNET_TIME_UNIT_SECONDS.rel_value_us * s_after_epoch;
+  if (ret.abs_time.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us
+      != s_after_epoch)
+    ret = GNUNET_TIME_UNIT_FOREVER_TS;
+  return ret;
+}
+
+
 struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
 {
@@ -645,6 +802,13 @@ GNUNET_TIME_randomized_backoff (struct 
GNUNET_TIME_Relative rt,
 }
 
 
+bool
+GNUNET_TIME_absolute_is_zero (struct GNUNET_TIME_Absolute abs)
+{
+  return 0 == abs.abs_value_us;
+}
+
+
 struct GNUNET_TIME_Relative
 GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r)
 {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]