bug-gnulib
[Top][All Lists]
Advanced

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

Re: human-time?


From: Simon Josefsson
Subject: Re: human-time?
Date: Thu, 10 Jan 2008 18:26:05 +0100
User-agent: Gnus/5.110007 (No Gnus v0.7) Emacs/22.1 (gnu/linux)

Below is code as a starting point, the self-tests produces:

7 weeks 5 days 12 hours 44 minutes 31 seconds
7 weeks 5 days 12 hours 44 minutes 1 second
7 weeks 5 days 12 hours 1 minute 11 seconds
7 weeks 5 days 1 hour 44 minutes 31 seconds
7 weeks 1 day 12 hours 44 minutes 31 seconds
1 week 5 days 12 hours 44 minutes 31 seconds
1 week 1 day 1 hour 1 minute 1 second

Which seems OK.  The self test should strcmp these strings instead of
printing them, but right now printing is more useful.

I know the code can be cleaned up, and comments added, but right now I'm
mostly looking for comments on the general approach and on the function
prototype:

char *
human_readable_time (time_t age, unsigned int units)

I'd prefer if the module didn't use xvasprintf because I probably want
to use this in a library, and x* doesn't work well there (and there are
license problems too).

If we don't worry about translations, the largest string for one unit
would be '%d minutes', so we could put the output string in a buffer and
require the caller to allocate sufficient large buffer.  What do you
think?  Something like this:

char *
human_readable_time (time_t age, unsigned int units,
                     char *buf, size_t bufsiz);

Or possibly, to be able to find out the total length:

size_t
human_readable_time (time_t age, unsigned int units,
                     char *buf, size_t bufsiz);

this one would return the size of the string, regardless of whether that
fitted in the buf+bufsiz buffer.

The last one could be OK even if we allow translated strings.  However,
we could also do it like:

char *
human_readable_time (time_t age, unsigned int units);

and allow the function to return NULL on memory allocation errors (and
errno would be set).  Maybe this is cleaner, I find that functions that
use fixed-size buffers are difficult to use.  And there are no
performance issues to consider here, I think, so the cost of memory
allocation should be irrelevant.

Hm.  I just realized the function doesn't do rounding properly.  So if
only one unit is requested, and the time is '7 weeks 6 days' the
function would return '7 weeks' rather than the expected '8 weeks'.

Also, there is the problem of how long a month and a year is, it isn't
really well-defined.  This is mostly relevant if you use full precision,
otherwise the string is just an approximation anyway.

Thoughts?

/Simon
/* Test printing of human time distances.
   Copyright (C) 2008 Free Software Foundation, Inc.
   Written by Simon Josefsson.

   This program 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 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>

#include "human-time.h"

#include <stdlib.h>
#include <stdio.h>

int
main (int ac, char *av[])
{
  char *s;

  s = human_readable_time (4711471, 99);
  puts (s);
  free (s);

  s = human_readable_time (4711441, 99);
  puts (s);
  free (s);

  s = human_readable_time (4708871, 99);
  puts (s);
  free (s);

  s = human_readable_time (4671871, 99);
  puts (s);
  free (s);

  s = human_readable_time (4365871, 99);
  puts (s);
  free (s);

  s = human_readable_time (1082671, 99);
  puts (s);
  free (s);

  s = human_readable_time (694861, 99);
  puts (s);
  free (s);

  return 0;
}
/* human-time.h -- human readable time distance conversion

   Copyright (C) 2008 Free Software Foundation, Inc.

   This program 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 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Written by Simon Josefsson.  */

#ifndef HUMAN_TIME_H_
# define HUMAN_TIME_H_ 1

#include <time.h>

char *human_readable_time (time_t age, unsigned int units);

#endif /* HUMAN_H_ */
/* human-time.h -- human readable time distance conversion

   Copyright (C) 2008 Free Software Foundation, Inc.

   This program 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 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Written by Simon Josefsson.  */

#include <config.h>

#include "human-time.h"

#include <stdlib.h>
#include <xvasprintf.h>

char *
human_readable_time (time_t age, unsigned int units)
{
  char *str;

  if (age == 1)
    return xasprintf ("1 second");
  else if (age < 60)
    return xasprintf ("%d seconds", age);
  else if (age < 2 * 60)
    str = xasprintf ("1 minute"), age -= 60;
  else if (age < 60 * 60)
    str = xasprintf ("%d minutes", age / 60), age -= 60 * (age / 60);
  else if (age < 2 * 60 * 60)
    str = xasprintf ("1 hour"), age -= 60 * 60;
  else if (age < 24 * 60 * 60)
    str = xasprintf ("%d hours", age / 60 / 60),
      age -= 60 * 60 * (age / 60 / 60);
  else if (age < 2 * 24 * 60 * 60)
    str = xasprintf ("1 day"), age -= 24 * 60 * 60;
  else if (age < 7 * 24 * 60 * 60)
    str = xasprintf ("%d days", age / 24 / 60 / 60),
      age -= 24 * 60 * 60 * (age / 60 / 60 / 24);
  else if (age < 2 * 7 * 24 * 60 * 60)
    str = xasprintf ("1 week"), age -= 7 * 24 * 60 * 60;
  else
    str = xasprintf ("%d weeks", age / 7 / 24 / 60 / 60),
      age -= 7 * 24 * 60 * 60 * (age / 60 / 60 / 24 / 7);

  if (units > 0 && age > 0)
    {
      char *next;
      char *whole;

      next = human_readable_time (age, units - 1);

      whole = xasprintf ("%s %s", str, next);
      free (str);
      free (next);

      str = whole;
    }

  return str;
}
Description:
Convert a time distance to a human readable string.

Files:
lib/human-time.h
lib/human-time.c
m4/human-time.m4

Depends-on:
xvasprintf

configure.ac:
gl_HUMAN_TIME

Makefile.am:

Include:
"human_time.h"

License:
LGPLv2+

Maintainer:
Simon Josefsson
Files:
tests/test-human-time.c

Depends-on:

configure.ac:

Makefile.am:
TESTS += test-human-time
check_PROGRAMS += test-human-time

License:
LGPLv2+
#serial 1
dnl Copyright (C) 2008 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

AC_DEFUN([gl_HUMAN_TIME],
[
  AC_LIBOBJ([human-time])

  dnl Prerequisites of lib/human-time.c.
  :
])

reply via email to

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