Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 9dec6d43e72ca3acc3cd14acfa66046617913505)
+++ uspace/lib/c/generic/time.c	(revision f7ea54007c430389f32534f3b3ec662f2dad8fe7)
@@ -841,25 +841,51 @@
 }
 
-struct tm *gmtime(const time_t *timer)
-{
-	assert(timer != NULL);
-
-	static struct tm result;
+
+/** Converts a time value to a broken-down UTC time
+ *
+ * @param time    Time to convert
+ * @param result  Structure to store the result to
+ *
+ * @return        EOK or a negative error code
+ */
+int utctime2tm(const time_t time, struct tm *restrict result)
+{
+	assert(result != NULL);
 
 	/* Set result to epoch. */
-	result.tm_sec = 0;
-	result.tm_min = 0;
-	result.tm_hour = 0;
-	result.tm_mday = 1;
-	result.tm_mon = 0;
-	result.tm_year = 70; /* 1970 */
-
-	if (_normalize_time(&result, *timer) == -1) {
-		errno = EOVERFLOW;
-		return NULL;
-	}
-
-	return &result;
-}
+	result->tm_sec = 0;
+	result->tm_min = 0;
+	result->tm_hour = 0;
+	result->tm_mday = 1;
+	result->tm_mon = 0;
+	result->tm_year = 70; /* 1970 */
+
+	if (_normalize_time(result, time) == -1)
+		return EOVERFLOW;
+
+	return EOK;
+}
+
+/** Converts a time value to a null terminated string of the form
+ *  "Wed Jun 30 21:49:08 1993\n" expressed in UTC.
+ *
+ * @param time   Time to convert.
+ * @param buf    Buffer to store the string to, must be at least
+ *               ASCTIME_BUF_LEN bytes long.
+ *
+ * @return       EOK or a negative error code.
+ */
+int utctime2str(const time_t time, char *restrict buf)
+{
+	struct tm t;
+	int r;
+
+	if ((r = utctime2tm(time, &t)) != EOK)
+		return r;
+
+	tm2str(&t, buf);
+	return EOK;
+}
+
 
 /**
@@ -868,11 +894,11 @@
  *
  * @param timeptr Broken-down time structure.
- * @return Pointer to a statically allocated string.
- */
-char *asctime(const struct tm *timeptr)
-{
-	static char buf[ASCTIME_BUF_LEN];
-
+ * @param buf     Buffer to store string to, must be at least ASCTIME_BUF_LEN
+ *                bytes long.
+ */
+void tm2str(const struct tm *restrict timeptr, char *restrict buf)
+{
 	assert(timeptr != NULL);
+	assert(buf != NULL);
 
 	static const char *wday[] = {
@@ -890,51 +916,56 @@
 	    timeptr->tm_min, timeptr->tm_sec,
 	    1900 + timeptr->tm_year);
-
-	return buf;
-
-}
-
-/**
- * Converts a time value to a broken-down local time.
- *
- * @param timer Time to convert.
- * @return Normalized broken-down time in local timezone, NULL on overflow.
- */
-struct tm *localtime(const time_t *timer)
+}
+
+/**
+ * Converts a time value to a broken-down local time, expressed relative
+ * to the user's specified timezone.
+ *
+ * @param timer     Time to convert.
+ * @param result    Structure to store the result to.
+ *
+ * @return          EOK on success or a negative error code.
+ */
+int localtime2tm(const time_t time, struct tm *restrict result)
 {
 	// TODO: deal with timezone
 	// currently assumes system and all times are in GMT
 
-	static struct tm result;
-
 	/* Set result to epoch. */
-	result.tm_sec = 0;
-	result.tm_min = 0;
-	result.tm_hour = 0;
-	result.tm_mday = 1;
-	result.tm_mon = 0;
-	result.tm_year = 70; /* 1970 */
-
-	if (_normalize_time(&result, *timer) == -1) {
-		errno = EOVERFLOW;
-		return NULL;
-	}
-
-	return &result;
-}
-
-/**
- * Equivalent to asctime(localtime(clock)).
+	result->tm_sec = 0;
+	result->tm_min = 0;
+	result->tm_hour = 0;
+	result->tm_mday = 1;
+	result->tm_mon = 0;
+	result->tm_year = 70; /* 1970 */
+
+	if (_normalize_time(result, time) == -1)
+		return EOVERFLOW;
+
+	return EOK;
+}
+
+/**
+ * Converts the calendar time to a null terminated string
+ * of the form "Wed Jun 30 21:49:08 1993\n" expressed relative to the
+ * user's specified timezone.
  * 
- * @param timer Time to convert.
- * @return Pointer to a statically allocated string holding the date.
- */
-char *ctime(const time_t *timer)
-{
-	struct tm *loctime = localtime(timer);
-	if (loctime == NULL) {
-		return NULL;
-	}
-	return asctime(loctime);
+ * @param timer  Time to convert.
+ * @param buf    Buffer to store the string to. Must be at least
+ *               ASCTIME_BUF_LEN bytes long.
+ *
+ * @return       EOK on success or a negative error code.
+ */
+int localtime2str(const time_t time, char *buf)
+{
+	struct tm loctime;
+	int r;
+
+	if ((r = localtime2tm(time, &loctime)) != EOK)
+		return r;
+
+	tm2str(&loctime, buf);
+
+	return EOK;
 }
 
Index: uspace/lib/c/include/sys/time.h
===================================================================
--- uspace/lib/c/include/sys/time.h	(revision 9dec6d43e72ca3acc3cd14acfa66046617913505)
+++ uspace/lib/c/include/sys/time.h	(revision f7ea54007c430389f32534f3b3ec662f2dad8fe7)
@@ -81,8 +81,9 @@
 
 extern time_t mktime(struct tm *tm);
-extern struct tm *gmtime(const time_t *timer);
-extern char *asctime(const struct tm *timeptr);
-extern struct tm *localtime(const time_t *timer);
-extern char *ctime(const time_t *timer);
+extern int utctime2tm(const time_t time, struct tm *result);
+extern int utctime2str(const time_t time, char *buf);
+extern void tm2str(const struct tm *timeptr, char *buf);
+extern int localtime2tm(const time_t time, struct tm *result);
+extern int localtime2str(const time_t time, char *buf);
 extern double difftime(time_t time1, time_t time0);
 extern size_t strftime(char *restrict s, size_t maxsize,
Index: uspace/lib/posix/time.c
===================================================================
--- uspace/lib/posix/time.c	(revision 9dec6d43e72ca3acc3cd14acfa66046617913505)
+++ uspace/lib/posix/time.c	(revision f7ea54007c430389f32534f3b3ec662f2dad8fe7)
@@ -61,238 +61,4 @@
  */
 
-
-
-/* Helper functions ***********************************************************/
-
-#define HOURS_PER_DAY (24)
-#define MINS_PER_HOUR (60)
-#define SECS_PER_MIN (60)
-#define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
-#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
-#define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
-
-/**
- * Checks whether the year is a leap year.
- *
- * @param year Year since 1900 (e.g. for 1970, the value is 70).
- * @return true if year is a leap year, false otherwise
- */
-static bool _is_leap_year(time_t year)
-{
-	year += 1900;
-
-	if (year % 400 == 0)
-		return true;
-	if (year % 100 == 0)
-		return false;
-	if (year % 4 == 0)
-		return true;
-	return false;
-}
-
-/**
- * Returns how many days there are in the given month of the given year.
- * Note that year is only taken into account if month is February.
- *
- * @param year Year since 1900 (can be negative).
- * @param mon Month of the year. 0 for January, 11 for December.
- * @return Number of days in the specified month.
- */
-static int _days_in_month(time_t year, time_t mon)
-{
-	assert(mon >= 0 && mon <= 11);
-
-	static int month_days[] =
-		{ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-	if (mon == 1) {
-		year += 1900;
-		/* february */
-		return _is_leap_year(year) ? 29 : 28;
-	} else {
-		return month_days[mon];
-	}
-}
-
-/**
- * For specified year, month and day of month, returns which day of that year
- * it is.
- *
- * For example, given date 2011-01-03, the corresponding expression is:
- *     _day_of_year(111, 0, 3) == 2
- *
- * @param year Year (year 1900 = 0, can be negative).
- * @param mon Month (January = 0).
- * @param mday Day of month (First day is 1).
- * @return Day of year (First day is 0).
- */
-static int _day_of_year(time_t year, time_t mon, time_t mday)
-{
-	static int mdays[] =
-	    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-	static int leap_mdays[] =
-	    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
-
-	return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
-}
-
-/**
- * Integer division that rounds to negative infinity.
- * Used by some functions in this file.
- *
- * @param op1 Dividend.
- * @param op2 Divisor.
- * @return Rounded quotient.
- */
-static time_t _floor_div(time_t op1, time_t op2)
-{
-	if (op1 >= 0 || op1 % op2 == 0) {
-		return op1 / op2;
-	} else {
-		return op1 / op2 - 1;
-	}
-}
-
-/**
- * Modulo that rounds to negative infinity.
- * Used by some functions in this file.
- *
- * @param op1 Dividend.
- * @param op2 Divisor.
- * @return Remainder.
- */
-static time_t _floor_mod(time_t op1, time_t op2)
-{
-	int div = _floor_div(op1, op2);
-
-	/* (a / b) * b + a % b == a */
-	/* thus, a % b == a - (a / b) * b */
-
-	int result = op1 - div * op2;
-	
-	/* Some paranoid checking to ensure I didn't make a mistake here. */
-	assert(result >= 0);
-	assert(result < op2);
-	assert(div * op2 + result == op1);
-	
-	return result;
-}
-
-/**
- * Number of days since the Epoch.
- * Epoch is 1970-01-01, which is also equal to day 0.
- *
- * @param year Year (year 1900 = 0, may be negative).
- * @param mon Month (January = 0).
- * @param mday Day of month (first day = 1).
- * @return Number of days since the Epoch.
- */
-static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
-{
-	return (year - 70) * 365 + _floor_div(year - 69, 4) -
-	    _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
-	    _day_of_year(year, mon, mday);
-}
-
-/**
- * Which day of week the specified date is.
- * 
- * @param year Year (year 1900 = 0).
- * @param mon Month (January = 0).
- * @param mday Day of month (first = 1).
- * @return Day of week (Sunday = 0).
- */
-static int _day_of_week(time_t year, time_t mon, time_t mday)
-{
-	/* 1970-01-01 is Thursday */
-	return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
-}
-
-/**
- * Normalizes the broken-down time and optionally adds specified amount of
- * seconds.
- * 
- * @param tm Broken-down time to normalize.
- * @param sec_add Seconds to add.
- * @return 0 on success, -1 on overflow
- */
-static int _normalize_time(struct tm *tm, time_t sec_add)
-{
-	// TODO: DST correction
-
-	/* Set initial values. */
-	time_t sec = tm->tm_sec + sec_add;
-	time_t min = tm->tm_min;
-	time_t hour = tm->tm_hour;
-	time_t day = tm->tm_mday - 1;
-	time_t mon = tm->tm_mon;
-	time_t year = tm->tm_year;
-
-	/* Adjust time. */
-	min += _floor_div(sec, SECS_PER_MIN);
-	sec = _floor_mod(sec, SECS_PER_MIN);
-	hour += _floor_div(min, MINS_PER_HOUR);
-	min = _floor_mod(min, MINS_PER_HOUR);
-	day += _floor_div(hour, HOURS_PER_DAY);
-	hour = _floor_mod(hour, HOURS_PER_DAY);
-
-	/* Adjust month. */
-	year += _floor_div(mon, 12);
-	mon = _floor_mod(mon, 12);
-
-	/* Now the difficult part - days of month. */
-	
-	/* First, deal with whole cycles of 400 years = 146097 days. */
-	year += _floor_div(day, 146097) * 400;
-	day = _floor_mod(day, 146097);
-	
-	/* Then, go in one year steps. */
-	if (mon <= 1) {
-		/* January and February. */
-		while (day > 365) {
-			day -= _is_leap_year(year) ? 366 : 365;
-			year++;
-		}
-	} else {
-		/* Rest of the year. */
-		while (day > 365) {
-			day -= _is_leap_year(year + 1) ? 366 : 365;
-			year++;
-		}
-	}
-	
-	/* Finally, finish it off month per month. */
-	while (day >= _days_in_month(year, mon)) {
-		day -= _days_in_month(year, mon);
-		mon++;
-		if (mon >= 12) {
-			mon -= 12;
-			year++;
-		}
-	}
-	
-	/* Calculate the remaining two fields. */
-	tm->tm_yday = _day_of_year(year, mon, day + 1);
-	tm->tm_wday = _day_of_week(year, mon, day + 1);
-	
-	/* And put the values back to the struct. */
-	tm->tm_sec = (int) sec;
-	tm->tm_min = (int) min;
-	tm->tm_hour = (int) hour;
-	tm->tm_mday = (int) day + 1;
-	tm->tm_mon = (int) mon;
-	
-	/* Casts to work around libc brain-damage. */
-	if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
-		tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
-		return -1;
-	}
-	
-	tm->tm_year = (int) year;
-	return 0;
-}
-
-/******************************************************************************/
-
 int posix_daylight;
 long posix_timezone;
@@ -321,21 +87,26 @@
     struct tm *restrict result)
 {
-	assert(timer != NULL);
-	assert(result != NULL);
-
-	/* Set result to epoch. */
-	result->tm_sec = 0;
-	result->tm_min = 0;
-	result->tm_hour = 0;
-	result->tm_mday = 1;
-	result->tm_mon = 0;
-	result->tm_year = 70; /* 1970 */
-
-	if (_normalize_time(result, *timer) == -1) {
-		errno = EOVERFLOW;
+	int rc = utctime2tm(*timer, result);
+	if (rc != EOK) {
+		errno = rc;
 		return NULL;
 	}
 
 	return result;
+}
+
+/**
+ * Converts a time value to a broken-down UTC time.
+ * (non reentrant version)
+ *
+ * @param timep  Time to convert
+ * @return       Pointer to a statically allocated structure that stores
+ *               the result, NULL in case of error.
+ */
+struct tm *posix_gmtime(const time_t *restrict timep)
+{
+	static struct tm result;
+
+	return posix_gmtime_r(timep, &result);
 }
 
@@ -353,4 +124,19 @@
 	// currently assumes system and all times are in GMT
 	return posix_gmtime_r(timer, result);
+}
+
+/**
+ * Converts a time value to a broken-down local time.
+ * (non reentrant version)
+ *
+ * @param timep    Time to convert.
+ * @return         Pointer to a statically allocated structure that stores
+ *                 the result, NULL in case of error.
+ */
+struct tm *posix_localtime(const time_t *restrict timep)
+{
+	static struct tm result;
+
+	return posix_localtime_r(timep, &result);
 }
 
@@ -367,40 +153,58 @@
     char *restrict buf)
 {
-	assert(timeptr != NULL);
-	assert(buf != NULL);
-
-	static const char *wday[] = {
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-	};
-	static const char *mon[] = {
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-	};
-
-	snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
-	    wday[timeptr->tm_wday],
-	    mon[timeptr->tm_mon],
-	    timeptr->tm_mday, timeptr->tm_hour,
-	    timeptr->tm_min, timeptr->tm_sec,
-	    1900 + timeptr->tm_year);
-
+	tm2str(timeptr, buf);
 	return buf;
 }
 
 /**
- * Reentrant variant of ctime().
+ * Convers broken-down time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
+ * (non reentrant version)
+ *
+ * @param timeptr    Broken-down time structure.
+ * @return           Pointer to a statically allocated buffer that stores
+ *                   the result, NULL in case of error.
+ */
+char *posix_asctime(const struct tm *restrict timeptr)
+{
+	static char buf[ASCTIME_BUF_LEN];
+
+	return posix_asctime_r(timeptr, buf);
+}
+
+/**
+ * Converts the calendar time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
  * 
  * @param timer Time to convert.
  * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
  *     bytes long.
- * @return Pointer to buf on success, NULL on falure.
+ * @return Pointer to buf on success, NULL on failure.
  */
 char *posix_ctime_r(const time_t *timer, char *buf)
 {
-	struct tm loctime;
-	if (posix_localtime_r(timer, &loctime) == NULL) {
+	int r = localtime2str(*timer, buf);
+	if (r != EOK) {
+		errno = r;
 		return NULL;
 	}
-	return posix_asctime_r(&loctime, buf);
+
+	return buf;
+}
+
+/**
+ * Converts the calendar time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
+ * (non reentrant version)
+ *
+ * @param timep    Time to convert.
+ * @return         Pointer to a statically allocated buffer that stores
+ *                 the result, NULL in case of error.
+ */
+char *posix_ctime(const time_t *timep)
+{
+	static char buf[ASCTIME_BUF_LEN];
+
+	return posix_ctime_r(timep, buf);
 }
 
Index: uspace/lib/posix/time.h
===================================================================
--- uspace/lib/posix/time.h	(revision 9dec6d43e72ca3acc3cd14acfa66046617913505)
+++ uspace/lib/posix/time.h	(revision f7ea54007c430389f32534f3b3ec662f2dad8fe7)
@@ -87,11 +87,15 @@
 extern struct tm *posix_gmtime_r(const time_t *restrict timer,
     struct tm *restrict result);
+extern struct tm *posix_gmtime(const time_t *restrict timep);
 extern struct tm *posix_localtime_r(const time_t *restrict timer,
     struct tm *restrict result);
+extern struct tm *posix_localtime(const time_t *restrict timep);
 
 /* Formatting Calendar Time */
 extern char *posix_asctime_r(const struct tm *restrict timeptr,
     char *restrict buf);
+extern char *posix_asctime(const struct tm *restrict timeptr);
 extern char *posix_ctime_r(const time_t *timer, char *buf);
+extern char *posix_ctime(const time_t *timer);
 
 /* Clocks */
@@ -109,18 +113,22 @@
 
 #ifndef LIBPOSIX_INTERNAL
-	#define timespec posix_timespec
-	#define itimerspec posix_itimerspec
-	#define timer_t posix_timer_t
+	#define timespec    posix_timespec
+	#define itimerspec  posix_itimerspec
+	#define timer_t     posix_timer_t
 
-	#define daylight posix_daylight
-	#define timezone posix_timezone
-	#define tzname posix_tzname
-	#define tzset posix_tzset
+	#define daylight    posix_daylight
+	#define timezone    posix_timezone
+	#define tzname      posix_tzname
+	#define tzset       posix_tzset
 
-	#define gmtime_r posix_gmtime_r
+	#define gmtime_r    posix_gmtime_r
+	#define gmtime      posix_gmtime
 	#define localtime_r posix_localtime_r
+	#define localtime   posix_localtime
 
-	#define asctime_r posix_asctime_r
-	#define ctime_r posix_ctime_r
+	#define asctime_r   posix_asctime_r
+	#define asctime     posix_asctime
+	#define ctime_r     posix_ctime_r
+	#define ctime       posix_ctime
 
 	#define clock_getres posix_clock_getres
