working again
[oweals/gnunet.git] / src / util / time.c
index f818fc9a12c282b4befef1596af106b4528d0b4e..a615756280b803db0a4925edf6341e9a73de0742 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2006, 2009 Christian Grothoff (and other contributing authors)
+     (C) 2001-2013 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  * @brief functions for handling time and time arithmetic
  */
 #include "platform.h"
  * @brief functions for handling time and time arithmetic
  */
 #include "platform.h"
-#include "gnunet_time_lib.h"
+#include "gnunet_util_lib.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
+/**
+ * Variable used to simulate clock skew.  Used for testing, never in production.
+ */
+static long long timestamp_offset;
+
+/**
+ * Set the timestamp offset for this instance.
+ *
+ * @param offset the offset to skew the locale time by
+ */
+void
+GNUNET_TIME_set_offset (long long offset)
+{
+  timestamp_offset = offset;
+}
+
+
+/**
+ * Get the timestamp offset for this instance.
+ *
+ * @return the offset we currently skew the locale time by
+ */
+long long
+GNUNET_TIME_get_offset ()
+{
+  return timestamp_offset;
+}
 
 
 /**
 
 
 /**
@@ -40,7 +70,9 @@ GNUNET_TIME_absolute_get ()
   struct timeval tv;
 
   GETTIMEOFDAY (&tv, NULL);
   struct timeval tv;
 
   GETTIMEOFDAY (&tv, NULL);
-  ret.value = (uint64_t) (((uint64_t) tv.tv_sec * 1000LL) + ((uint64_t) tv.tv_usec / 1000LL));
+  ret.abs_value_us =
+      (uint64_t) (((uint64_t) tv.tv_sec * 1000LL * 1000LL) +
+                  ((uint64_t) tv.tv_usec)) + timestamp_offset;
   return ret;
 }
 
   return ret;
 }
 
@@ -49,9 +81,10 @@ GNUNET_TIME_absolute_get ()
  * Return relative time of 0ms.
  */
 struct GNUNET_TIME_Relative
  * Return relative time of 0ms.
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_relative_get_zero ()
+GNUNET_TIME_relative_get_zero_ ()
 {
   static struct GNUNET_TIME_Relative zero;
 {
   static struct GNUNET_TIME_Relative zero;
+
   return zero;
 }
 
   return zero;
 }
 
@@ -60,29 +93,76 @@ GNUNET_TIME_relative_get_zero ()
  * Return absolute time of 0ms.
  */
 struct GNUNET_TIME_Absolute
  * Return absolute time of 0ms.
  */
 struct GNUNET_TIME_Absolute
-GNUNET_TIME_absolute_get_zero ()
+GNUNET_TIME_absolute_get_zero_ ()
 {
   static struct GNUNET_TIME_Absolute zero;
 {
   static struct GNUNET_TIME_Absolute zero;
+
   return zero;
 }
 
   return zero;
 }
 
+
 /**
 /**
- * Return relative time of 1ms.
+ * Return relative time of 1us.
  */
 struct GNUNET_TIME_Relative
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_relative_get_unit ()
+GNUNET_TIME_relative_get_unit_ ()
 {
   static struct GNUNET_TIME_Relative one = { 1 };
   return one;
 }
 
 {
   static struct GNUNET_TIME_Relative one = { 1 };
   return one;
 }
 
+
+/**
+ * Return relative time of 1ms.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_millisecond_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 1000 };
+  return one;
+}
+
+
+/**
+ * Return relative time of 1s.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_second_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 1000 * 1000LL };
+  return one;
+}
+
+
+/**
+ * Return relative time of 1 minute.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_minute_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 60 * 1000 * 1000LL };
+  return one;
+}
+
+
+/**
+ * Return relative time of 1 hour.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_hour_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 60 * 60 * 1000 * 1000LL };
+  return one;
+}
+
+
 /**
  * Return "forever".
  */
 struct GNUNET_TIME_Relative
 /**
  * Return "forever".
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_relative_get_forever ()
+GNUNET_TIME_relative_get_forever_ ()
 {
 {
-  static struct GNUNET_TIME_Relative forever = { (uint64_t) - 1LL };
+  static struct GNUNET_TIME_Relative forever = { UINT64_MAX };
   return forever;
 }
 
   return forever;
 }
 
@@ -90,9 +170,9 @@ GNUNET_TIME_relative_get_forever ()
  * Return "forever".
  */
 struct GNUNET_TIME_Absolute
  * Return "forever".
  */
 struct GNUNET_TIME_Absolute
-GNUNET_TIME_absolute_get_forever ()
+GNUNET_TIME_absolute_get_forever_ ()
 {
 {
-  static struct GNUNET_TIME_Absolute forever = { (uint64_t) - 1LL };
+  static struct GNUNET_TIME_Absolute forever = { UINT64_MAX };
   return forever;
 }
 
   return forever;
 }
 
@@ -106,15 +186,17 @@ struct GNUNET_TIME_Absolute
 GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
 {
   struct GNUNET_TIME_Absolute ret;
 GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
 {
   struct GNUNET_TIME_Absolute ret;
-  if (rel.value == (uint64_t) -1LL)
-    return GNUNET_TIME_absolute_get_forever ();
+
+  if (rel.rel_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  if (rel.value + now.value < rel.value)
-    {
-      GNUNET_break (0);         /* overflow... */
-      return GNUNET_TIME_absolute_get_forever ();
-    }
-  ret.value = rel.value + now.value;
+
+  if (rel.rel_value_us + now.abs_value_us < rel.rel_value_us)
+  {
+    GNUNET_break (0);           /* overflow... */
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
+  }
+  ret.abs_value_us = rel.rel_value_us + now.abs_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -122,17 +204,64 @@ GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
 /**
  * Return the minimum of two relative time values.
  *
 /**
  * Return the minimum of two relative time values.
  *
+ * @param t1 first timestamp
+ * @param t2 other timestamp
+ * @return timestamp that is smaller
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
+                          struct GNUNET_TIME_Relative t2)
+{
+  return (t1.rel_value_us < t2.rel_value_us) ? t1 : t2;
+}
+
+
+/**
+ * Return the maximum of two relative time values.
+ *
+ * @param t1 first timestamp
+ * @param t2 other timestamp
+ * @return timestamp that is larger
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
+                          struct GNUNET_TIME_Relative t2)
+{
+  return (t1.rel_value_us > t2.rel_value_us) ? t1 : t2;
+}
+
+
+
+/**
+ * Return the minimum of two relative time values.
+ *
+ * @param t1 first timestamp
+ * @param t2 other timestamp
  * @return timestamp that is smaller
  */
  * @return timestamp that is smaller
  */
-struct GNUNET_TIME_Relative GNUNET_TIME_relative_min (struct
-                                                     GNUNET_TIME_Relative
-                                                     t1,
-                                                     struct
-                                                     GNUNET_TIME_Relative t2)
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
+                          struct GNUNET_TIME_Absolute t2)
+{
+  return (t1.abs_value_us < t2.abs_value_us) ? t1 : t2;
+}
+
+
+/**
+ * Return the maximum of two relative time values.
+ *
+ * @param t1 first timestamp
+ * @param t2 other timestamp
+ * @return timestamp that is bigger
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
+                          struct GNUNET_TIME_Absolute t2)
 {
 {
-  return (t1.value < t2.value) ? t1 : t2;
+  return (t1.abs_value_us > t2.abs_value_us) ? t1 : t2;
 }
 
 }
 
+
 /**
  * Given a timestamp in the future, how much time
  * remains until then?
 /**
  * Given a timestamp in the future, how much time
  * remains until then?
@@ -143,19 +272,21 @@ struct GNUNET_TIME_Relative
 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
 {
   struct GNUNET_TIME_Relative ret;
 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
 {
   struct GNUNET_TIME_Relative ret;
-  if (future.value == (uint64_t) - 1LL)
-    return GNUNET_TIME_relative_get_forever ();
+
+  if (future.abs_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  if (now.value > future.value)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.value = future.value - now.value;
+
+  if (now.abs_value_us > future.abs_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  ret.rel_value_us = future.abs_value_us - now.abs_value_us;
   return ret;
 }
 
 /**
  * Compute the time difference between the given start and end times.
  * Use this function instead of actual subtraction to ensure that
   return ret;
 }
 
 /**
  * Compute the time difference between the given start and end times.
  * Use this function instead of actual subtraction to ensure that
- * "FOREVER" and overflows are handeled correctly.
+ * "FOREVER" and overflows are handled correctly.
  *
  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
  */
  *
  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
  */
@@ -164,31 +295,32 @@ GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
                                      struct GNUNET_TIME_Absolute end)
 {
   struct GNUNET_TIME_Relative ret;
                                      struct GNUNET_TIME_Absolute end)
 {
   struct GNUNET_TIME_Relative ret;
-  if (end.value == (uint64_t) - 1LL)
-    return GNUNET_TIME_relative_get_forever ();
-  if (end.value < start.value)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.value = end.value - start.value;
+
+  if (end.abs_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  if (end.abs_value_us < start.abs_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  ret.rel_value_us = end.abs_value_us - start.abs_value_us;
   return ret;
 }
 
 /**
  * Get the duration of an operation as the
   return ret;
 }
 
 /**
  * Get the duration of an operation as the
- * difference of the current time and the given start time "hence".
+ * difference of the current time and the given start time "whence".
  *
  *
- * @return aborts if hence==FOREVER, 0 if hence > now, otherwise now-hence.
+ * @return aborts if whence==FOREVER, 0 if whence > now, otherwise now-whence.
  */
 struct GNUNET_TIME_Relative
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute hence)
+GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
 {
   struct GNUNET_TIME_Absolute now;
   struct GNUNET_TIME_Relative ret;
 
   now = GNUNET_TIME_absolute_get ();
 {
   struct GNUNET_TIME_Absolute now;
   struct GNUNET_TIME_Relative ret;
 
   now = GNUNET_TIME_absolute_get ();
-  GNUNET_assert (hence.value != (uint64_t) - 1LL);
-  if (hence.value > now.value)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.value = now.value - hence.value;
+  GNUNET_assert (whence.abs_value_us != UINT64_MAX);
+  if (whence.abs_value_us > now.abs_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  ret.rel_value_us = now.abs_value_us - whence.abs_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -205,18 +337,41 @@ GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
 {
   struct GNUNET_TIME_Absolute ret;
 
 {
   struct GNUNET_TIME_Absolute ret;
 
-  if ((start.value == (uint64_t) - 1LL) ||
-      (duration.value == (uint64_t) - 1LL))
-    return GNUNET_TIME_absolute_get_forever ();
-  if (start.value + duration.value < start.value)
-    {
-      GNUNET_break (0);
-      return GNUNET_TIME_absolute_get_forever ();
-    }
-  ret.value = start.value + duration.value;
+  if ((start.abs_value_us == UINT64_MAX) || (duration.rel_value_us == UINT64_MAX))
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
+  if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
+  {
+    GNUNET_break (0);
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
+  }
+  ret.abs_value_us = start.abs_value_us + duration.rel_value_us;
+  return ret;
+}
+
+
+/**
+ * Subtract a given relative duration from the
+ * given start time.
+ *
+ * @param start some absolute time
+ * @param duration some relative time to subtract
+ * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
+                               struct GNUNET_TIME_Relative duration)
+{
+  struct GNUNET_TIME_Absolute ret;
+
+  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)
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
+  ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
+
 /**
  * Multiply relative time by a given factor.
  *
 /**
  * Multiply relative time by a given factor.
  *
@@ -227,20 +382,44 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
                                unsigned int factor)
 {
   struct GNUNET_TIME_Relative ret;
                                unsigned int factor)
 {
   struct GNUNET_TIME_Relative ret;
-  if (factor == 0)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.value = rel.value * (unsigned long long) factor;
-  if (ret.value / factor != rel.value)
-    {
-      GNUNET_break (0);
-      return GNUNET_TIME_relative_get_forever ();
-    }  
+
+  if (0 == factor)
+    return GNUNET_TIME_UNIT_ZERO;
+  if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  ret.rel_value_us = rel.rel_value_us * (unsigned long long) factor;
+  if (ret.rel_value_us / factor != rel.rel_value_us)
+  {
+    GNUNET_break (0);
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  }
+  return ret;
+}
+
+
+/**
+ * Divide relative time by a given factor.
+ *
+ * @param rel some duration
+ * @param factor integer to divide by
+ * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
+                             unsigned int factor)
+{
+  struct GNUNET_TIME_Relative ret;
+
+  if ((0 == factor) ||
+      (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  ret.rel_value_us = rel.rel_value_us / (unsigned long long) factor;
   return ret;
 }
 
 
 /**
   return ret;
 }
 
 
 /**
- * Calculate the estimate time of arrival/completion 
+ * Calculate the estimate time of arrival/completion
  * for an operation.
  *
  * @param start when did the operation start?
  * for an operation.
  *
  * @param start when did the operation start?
@@ -249,22 +428,22 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
  * @return remaining duration for the operation,
  *        assuming it continues at the same speed
  */
  * @return remaining duration for the operation,
  *        assuming it continues at the same speed
  */
-struct GNUNET_TIME_Relative GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
-                                                      uint64_t finished,
-                                                      uint64_t total)
+struct GNUNET_TIME_Relative
+GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, uint64_t finished,
+                           uint64_t total)
 {
   struct GNUNET_TIME_Relative dur;
   double exp;
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative dur;
   double exp;
   struct GNUNET_TIME_Relative ret;
 
-  GNUNET_break (finished > total);
+  GNUNET_break (finished <= total);
   if (finished >= total)
     return GNUNET_TIME_UNIT_ZERO;
   if (finished >= total)
     return GNUNET_TIME_UNIT_ZERO;
-  if (finished == 0)
+  if (0 == finished)
     return GNUNET_TIME_UNIT_FOREVER_REL;
   dur = GNUNET_TIME_absolute_get_duration (start);
     return GNUNET_TIME_UNIT_FOREVER_REL;
   dur = GNUNET_TIME_absolute_get_duration (start);
-  exp = ((double)dur.value) * ((double) total) / ((double)finished);
-  ret.value = ((uint64_t) exp) - dur.value;
+  exp = ((double) dur.rel_value_us) * ((double) total) / ((double) finished);
+  ret.rel_value_us = ((uint64_t) exp) - dur.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -272,6 +451,8 @@ struct GNUNET_TIME_Relative GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolu
 /**
  * Add relative times together.
  *
 /**
  * Add relative times together.
  *
+ * @param a1 first timestamp
+ * @param a2 second timestamp
  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
  */
 struct GNUNET_TIME_Relative
  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
  */
 struct GNUNET_TIME_Relative
@@ -280,64 +461,174 @@ GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if ((a1.value == (uint64_t) - 1LL) || (a2.value == (uint64_t) - 1LL))
-    return GNUNET_TIME_relative_get_forever ();
-  if (a1.value + a2.value < a1.value)
-    {
-      GNUNET_break (0);
-      return GNUNET_TIME_relative_get_forever ();
-    }
-  ret.value = a1.value + a2.value;
+  if ((a1.rel_value_us == UINT64_MAX) || (a2.rel_value_us == UINT64_MAX))
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  if (a1.rel_value_us + a2.rel_value_us < a1.rel_value_us)
+  {
+    GNUNET_break (0);
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  }
+  ret.rel_value_us = a1.rel_value_us + a2.rel_value_us;
+  return ret;
+}
+
+
+/**
+ * Subtract relative timestamp from the other.
+ *
+ * @param a1 first timestamp
+ * @param a2 second timestamp
+ * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
+                               struct GNUNET_TIME_Relative a2)
+{
+  struct GNUNET_TIME_Relative ret;
+
+  if (a2.rel_value_us >= a1.rel_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  if (a1.rel_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  ret.rel_value_us = a1.rel_value_us - a2.rel_value_us;
   return ret;
 }
 
 
 /**
  * Convert relative time to network byte order.
   return ret;
 }
 
 
 /**
  * Convert relative time to network byte order.
+ *
+ * @param a time to convert
+ * @return time in network byte order
  */
 struct GNUNET_TIME_RelativeNBO
 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
 {
   struct GNUNET_TIME_RelativeNBO ret;
  */
 struct GNUNET_TIME_RelativeNBO
 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
 {
   struct GNUNET_TIME_RelativeNBO ret;
-  ret.value__ = GNUNET_htonll (a.value);
+
+  ret.rel_value_us__ = GNUNET_htonll (a.rel_value_us);
   return ret;
 }
 
   return ret;
 }
 
+
 /**
  * Convert relative time from network byte order.
 /**
  * Convert relative time from network byte order.
+ *
+ * @param a time to convert
+ * @return time in host byte order
  */
 struct GNUNET_TIME_Relative
 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
 {
   struct GNUNET_TIME_Relative ret;
  */
 struct GNUNET_TIME_Relative
 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
 {
   struct GNUNET_TIME_Relative ret;
-  ret.value = GNUNET_ntohll (a.value__);
+
+  ret.rel_value_us = GNUNET_ntohll (a.rel_value_us__);
   return ret;
 
 }
 
   return ret;
 
 }
 
+
 /**
  * Convert absolute time to network byte order.
 /**
  * Convert absolute time to network byte order.
+ *
+ * @param a time to convert
+ * @return time in network byte order
  */
 struct GNUNET_TIME_AbsoluteNBO
 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
 {
   struct GNUNET_TIME_AbsoluteNBO ret;
  */
 struct GNUNET_TIME_AbsoluteNBO
 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
 {
   struct GNUNET_TIME_AbsoluteNBO ret;
-  ret.value__ = GNUNET_htonll (a.value);
+
+  ret.abs_value_us__ = GNUNET_htonll (a.abs_value_us);
   return ret;
 }
 
   return ret;
 }
 
+
 /**
  * Convert absolute time from network byte order.
 /**
  * Convert absolute time from network byte order.
+ *
+ * @param a time to convert
+ * @return time in host byte order
  */
 struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
 {
   struct GNUNET_TIME_Absolute ret;
  */
 struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
 {
   struct GNUNET_TIME_Absolute ret;
-  ret.value = GNUNET_ntohll (a.value__);
+
+  ret.abs_value_us = GNUNET_ntohll (a.abs_value_us__);
   return ret;
 
 }
 
 
   return ret;
 
 }
 
 
+/**
+ * Return the current year (i.e. '2011').
+ */
+unsigned int
+GNUNET_TIME_get_current_year ()
+{
+  time_t tp;
+  struct tm *t;
+
+  tp = time (NULL);
+  t = gmtime (&tp);
+  if (t == NULL)
+    return 0;
+  return t->tm_year + 1900;
+}
+
+
+/**
+ * Convert an expiration time to the respective year (rounds)
+ *
+ * @param at absolute time
+ * @return year a year (after 1970), 0 on error
+ */
+unsigned int
+GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at)
+{
+  struct tm *t;
+  time_t tp;
+
+  tp = at.abs_value_us / 1000LL / 1000LL;    /* microseconds to seconds */
+  t = gmtime (&tp);
+  if (t == NULL)
+    return 0;
+  return t->tm_year + 1900;
+
+}
+
+
+/**
+ * Convert a year to an expiration time of January 1st of that year.
+ *
+ * @param year a year (after 1970, please ;-)).
+ * @return absolute time for January 1st of that year.
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_year_to_time (unsigned int year)
+{
+  struct GNUNET_TIME_Absolute ret;
+  time_t tp;
+  struct tm t;
+
+  memset (&t, 0, sizeof (t));
+  if (year < 1900)
+  {
+    GNUNET_break (0);
+    return GNUNET_TIME_absolute_get (); /* now */
+  }
+  t.tm_year = year - 1900;
+  t.tm_mday = 1;
+  t.tm_mon = 1;
+  t.tm_wday = 1;
+  t.tm_yday = 1;
+  tp = mktime (&t);
+  GNUNET_break (tp != (time_t) - 1);
+  ret.abs_value_us = tp * 1000LL * 1000LL;  /* seconds to microseconds */
+  return ret;
+}
+
+
 
 /* end of time.c */
 
 /* end of time.c */