5d3d502000-02-24Martin Nilsson // This is a roxen module. Copyright © 1997 - 2000, Roxen IS. //
9b03652001-03-07Kenneth Johansson constant cvs_version="$Id: countdown.pike,v 1.41 2001/03/07 13:42:11 kuntri Exp $";
1cbdd51997-10-25Per Hedbor #include <module.h> inherit "module";
6a4ce21999-09-26Martin Nilsson constant thread_safe=1;
b3281f2000-09-10Martin Nilsson constant module_type = MODULE_TAG;
de5c3c2000-01-23Martin Nilsson constant module_name = "Countdown";
59ae152000-04-06Mattias Wingstedt constant module_doc = "Provides the <tt>&lt;countdown&gt;</tt> tag, that " "shows the time remaining until a certain date.";
b13cba1999-09-25Martin Nilsson 
e26d311999-12-14Martin Nilsson TAGDOCUMENTATION;
cfe42b1999-12-07Martin Nilsson #ifdef manual
9b03652001-03-07Kenneth Johansson constant tagdoc=([ constant tagdoc=(["countdown":#"<desc tag='tag'><p><short> This tag can count days, minutes, months, etc. from a specified date or time.</short> It can also give the time to or from a few special events. See below for a full list.</p></desc>
db0fbf1999-11-22Martin Nilsson  <p>Time:</p>
9b03652001-03-07Kenneth Johansson <attr name='year' value='number'><p>Sets the year.</p></attr> <attr name='month' value='number|month_name'><p>Sets the month.</p></attr> <attr name='day' value='number|day_name'><p>Sets the weekday.</p></attr> <attr name='mday' value='number'><p>Sets the day of the month.</p></attr> <attr name='hour' value='number'><p>Sets the hour.</p></attr> <attr name='minute' value='number'><p>Sets the minute.</p></attr> <attr name='second' value='number'><p>Sets the second.</p></attr> <attr name='iso' value='year-month-day'><p>Sets the year, month and day all at once. (YYYY-MM-DD, YYYYMMDD or YYYY-MMM-DD).</p>
d2030d2000-05-02Kenneth Johansson <ex><countdown iso='2020-FEB-12'/></ex>
3bb0d32000-04-30Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson <attr name='event' value='easter,gregorian-easter,julian-easter,christmas,christmas-day,christmas-eve'><p> Sets the time of an event to count down to.</p></attr>
d2030d2000-05-02Kenneth Johansson 
9b03652001-03-07Kenneth Johansson <attr name='years' value='number'><p>Add this number of years to the result.</p></attr> <attr name='months' value='number'><p>Add this number of months to the result.</p></attr> <attr name='weeks' value='number'><p>Add this number of weeks to the result.</p></attr> <attr name='days' value='number'><p>Add this number of days to the result.</p></attr> <attr name='hours' value='number'><p>Add this number of hours to the result.</p></attr> <attr name='beats' value='number'><p>Add this number of beats to the result.</p></attr> <attr name='minutes' value='number'><p>Add this number of minutes to the result.</p></attr> <attr name='seconds' value='number'><p>Add this number of seconds to the result.</p></attr> <attr name='now' value='year-month-day'><p>Sets the 'present' time, if other than really present time. (YYYY-MM-DD, YYYYMMDD or YYYY-MMM-DD)</p>
d2030d2000-05-02Kenneth Johansson 
3bb0d32000-04-30Martin Nilsson <ex><countdown now=\"1999-12-24\" year=\"2000\" display=\"days\"/></ex> </attr>
db0fbf1999-11-22Martin Nilsson 
d2030d2000-05-02Kenneth Johansson 
db0fbf1999-11-22Martin Nilsson <p>Presentation:</p>
9b03652001-03-07Kenneth Johansson <attr name='display' value='when|years|months|weeks|days|hours|beats|minutes|seconds|combined|dogyears|boolean>
f8dd6d2000-09-18Kenneth Johansson <xtable> <row><c><i>display=when</i></c><c>Shows when the time will occur.
9b03652001-03-07Kenneth Johansson  All arguments that are valid in <xref href='date.tag' /> can be used to modify the display.</c></row>
f8dd6d2000-09-18Kenneth Johansson <row><c><i>display=years</i></c><c>How many years until the time.</c></row> <row><c><i>display=months</i></c><c>How many months until the time.</c></row> <row><c><i>display=weeks</i></c><c>How many weeks until the time.</c></row> <row><c><i>display=days</i></c><c>How many days until the time.</c></row> <row><c><i>display=hours</i></c><c>How many hours until the time. <ex><countdown day=\"friday\" display=\"hours\"/></ex></c></row> <row><c><i>display=beats</i></c><c>How many beats until the time.</c></row> <row><c><i>display=minutes</i></c><c>How many minutes until the time.</c></row> <row><c><i>display=seconds</i></c><c>How many seconds until the time.</c></row> <row><c><i>display=combined</i></c><c>Shows an english text describing the time period.
db0fbf1999-11-22Martin Nilsson  Example: 2 days, 1 hour and 5 seconds. You may use the 'prec' attribute to limit how precise the description is. Also, you can use the 'month' attribute if you want to see years/months/days
d2030d2000-05-02Kenneth Johansson  instead of years/weeks/days.
f8dd6d2000-09-18Kenneth Johansson <ex type='vert'>The world will go under in <countdown year='2038' display='combined' prec='day'/>.</ex></c></row> <row><c><i>display=dogyears</i></c><c>How many dog-years until the time. (With one decimal) <ex><countdown years=\"2\" display=\"dogyears\"/></ex></c></row>
9b03652001-03-07Kenneth Johansson <row><c><i>display=boolean</i></c><c>Return true or false (1 or 0), depending on if the time is now or not. The fuzziness of 'now' is decided by the 'prec' option. <ex type='vert'><b>Is this a Sunday?</b>
d2030d2000-05-02Kenneth Johansson <define variable='var.test' preparse=''><countdown day='sunday' display='boolean'/></define> <if variable='var.test = 1'>Yes, this is a Sunday.</if> <else>No, it isn´t.</else></ex>
9b03652001-03-07Kenneth Johansson </c></row>
f8dd6d2000-09-18Kenneth Johansson </xtable>
db0fbf1999-11-22Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='type' value='type'><p>As for 'date'. Useful values for type include string, number and ordered.</p></attr> <attr name='lang' value='langcodes'><p>The language in which the result should be written if the type is string.</p>
d2030d2000-05-02Kenneth Johansson  <ex type='vert'>Heute ist es ungefähr <countdown event='christmas' display='months' type='string' lang='de'/> Monate bis Weinachten.</ex> </attr>
9b03652001-03-07Kenneth Johansson  <attr name='since'><p>Negate the period of time.</p> <ex type='vert'> I am <countdown iso='1980-06-28' since='' display='years' type='string'/> years old.</ex>
d2030d2000-05-02Kenneth Johansson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='next'><p>Always count down to the next event. <tag>countdown day='friday' next=''</tag> says 6 on a friday as opposed to 0 without the next attribute.</p>
d2030d2000-05-02Kenneth Johansson  <ex type='vert'>It is <countdown day='monday' next=''/> to monday.</ex>
91d6cd2000-03-21Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson <attr name='prec' value='year|month|week|day|hour|minute|second'><p>Modifies the precision for 'boolean'- and 'combined'-arguments.</p></attr>" ]);
cfe42b1999-12-07Martin Nilsson #endif
db0fbf1999-11-22Martin Nilsson 
2d94ef1999-07-19Martin Nilsson mapping set_to_julian_easter(int year) { int G = year % 19; int I = (19*G + 15) % 30; int J = (year + year/4 + I) % 7; int L = I - J;
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson  mapping easter=([]);
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson  easter->mon=3 + (L + 40)/44; easter->day=L + 28 - 31*(easter->mon/4); return easter; }
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson mapping set_to_gregorian_easter(int year) { int G = year % 19; int C = year / 100; int H = (C - C/4 - (8*C+13)/25 + 19*G + 15) % 30; int I = H - (H/28)*(1 - (H/28)*(29/(H + 1))*((21 - G)/11)); int J = (year + year/4 + I + 2 - C + C/4) % 7; int L = I - J;
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson  mapping easter=([]);
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson  easter->mon=3 + (L + 40)/44; easter->day=L + 28 - 31*(easter->mon/4); return easter; }
1cbdd51997-10-25Per Hedbor 
e26d311999-12-14Martin Nilsson void start( int num, Configuration conf ) { module_dependencies (conf, ({ "rxmltags" })); }
59ec112000-02-15Martin Nilsson array languages = roxen->list_languages(); constant language_low = roxen->language_low;
1cbdd51997-10-25Per Hedbor int find_a_month(string which) { which = lower_case(which);
59ec112000-02-15Martin Nilsson  foreach(languages, string lang)
1cbdd51997-10-25Per Hedbor  for(int i=1; i<13; i++)
8756ae1998-03-08Per Hedbor  catch {
6f8d082000-02-15Martin Nilsson  if(which == lower_case(language_low(lang)->month(i))[..strlen(which)])
1cbdd51997-10-25Per Hedbor  return i-1;
8756ae1998-03-08Per Hedbor  };
1cbdd51997-10-25Per Hedbor  return 1; } int find_a_day(string which) { which = lower_case(which);
6f8d082000-02-15Martin Nilsson  foreach(languages, string lang)
1cbdd51997-10-25Per Hedbor  for(int i=1; i<8; i++)
59ec112000-02-15Martin Nilsson  if(which == lower_case(language_low(lang)->day(i))[..strlen(which)])
1cbdd51997-10-25Per Hedbor  return i; return 1; }
de5c3c2000-01-23Martin Nilsson constant language=roxen->language; string show_number(int n, mapping m, RequestID id)
1cbdd51997-10-25Per Hedbor {
1a73582000-04-30Martin Nilsson  return Roxen.number2string(n, m, language(m->lang||id->misc->defines->pref_language, m->ordered?"ordered":"number", id));
1cbdd51997-10-25Per Hedbor }
6eac091998-07-18Fredrik Hübinette (Hubbe) // This function should be fixed to support different languages. // Possibly even implemented in the language module itself. // Hubbe
2d94ef1999-07-19Martin Nilsson string time_period(int t, int prec)
6eac091998-07-18Fredrik Hübinette (Hubbe) { int i;
cd1dde2000-02-17Per Hedbor  array(string) tmp=({});
6eac091998-07-18Fredrik Hübinette (Hubbe)  if(!t) return "zero seconds";
2d94ef1999-07-19Martin Nilsson  i=t%60; if(i && prec<60) tmp=({i+ " second"+(i==1?"":"s") });
6eac091998-07-18Fredrik Hübinette (Hubbe)  t/=60;
2d94ef1999-07-19Martin Nilsson  i=t&60; if(i && prec<3600) tmp=({i+ " minute"+(i==1?"":"s") })+tmp;
6eac091998-07-18Fredrik Hübinette (Hubbe)  t/=60;
2d94ef1999-07-19Martin Nilsson  i=t%24; if(i && prec<3600*24) tmp=({i+ " hour"+(i==1?"":"s") })+tmp;
6eac091998-07-18Fredrik Hübinette (Hubbe)  t/=24;
2d94ef1999-07-19Martin Nilsson  if(prec==3600*24*7) { if(i=t/365) tmp=({i+ " year"+(i==1?"":"s") }); t-=365*i; if(i=t/7) tmp+=({i+ " week"+(i==1?"":"s") }); t-=7*i; if(t) tmp+=({i+ " day"+(i==1?"":"s") }); return String.implode_nicely(tmp);
6eac091998-07-18Fredrik Hübinette (Hubbe)  }
2d94ef1999-07-19Martin Nilsson  float days_per_year = 365.242190; // Y28K safe float days_per_month = days_per_year/12; float s=(float)t; i=(int)(t%days_per_month); if(i && prec<(int)(3600*24*days_per_month)) tmp=({i+" day"+(i==1?"":"s") })+tmp; s=t/days_per_month; i=(int)(s%12); if(i && prec<(int)(3600*24*days_per_year)) tmp=({i+" month"+(i==1?"":"s") })+tmp; s=(s/12)*1.000664; if(i=(int)s) tmp=({i+" year"+(i==1?"":"s") })+tmp;
6eac091998-07-18Fredrik Hübinette (Hubbe)  return String.implode_nicely(tmp); }
2d94ef1999-07-19Martin Nilsson mapping clear_less_significant(mapping m, string from) { switch(from) { case "year": m->mon=0; case "mon": m->mday=1; case "day": m->hour=0; case "hour": m->min=0; case "min": m->sec=0; return m; } } int unset_from(mapping m, string from) { switch(from) { case "sec": if(m->minute) return 0; case "min": if(m->hour) return 0; case "hour": if(m->wday) return 0; case "wday": if(m->mday || m->iso) return 0; case "day": if(m->month || m->iso) return 0; case "mon": if(m->year || m->iso) return 0; return 1; } } int weekday_handler(int when, mapping time_args) { while((localtime(when)->wday) != (time_args->wday)) when += 3600*24; return when; }
903f532000-06-13Martin Nilsson class TagCountdown { inherit RXML.Tag; constant name = "countdown"; constant flags = RXML.FLAG_EMPTY_ELEMENT; class Frame { inherit RXML.Frame; array do_return(RequestID id) { result = countdown(args, id); return 0; } } } string countdown(mapping m, RequestID id)
1cbdd51997-10-25Per Hedbor {
2d94ef1999-07-19Martin Nilsson  if(m->sec || m->prec=="second") CACHE(1); else CACHE(59);
90da991998-08-10Per Hedbor 
2d94ef1999-07-19Martin Nilsson  float days_per_year = 365.242190; // Y28K safe string tprec;
b137461999-08-26Martin Nilsson  int unix_now = time(1); if(m->now) { mapping newnow=([]);
c9e6c92000-02-16Per Hedbor  if(sscanf(m->now, "%d-%d-%d",
b137461999-08-26Martin Nilsson  newnow->year, newnow->mon, newnow->mday)==3 || sscanf(m->now, "%4d%2d%2d", newnow->year, newnow->mon, newnow->mday)==3 || sscanf(m->now, "%d-%s-%d", newnow->year, newnow->mon, newnow->mday) == 3) { if (stringp(newnow->mon)) newnow->mon = ([ "jan": 1, "feb": 2, "mar": 3, "apr": 4, "may": 5, "jun": 6, "jul": 7, "aug": 8, "sep": 9, "oct": 10, "nov": 11, "dec": 12 ]) [lower_case(sprintf("%s", newnow->mon))[0..2]]; if (newnow->year>1900) newnow->year-=1900; newnow->mon--; if(catch { unix_now = mktime(newnow); })
5d3d502000-02-24Martin Nilsson  RXML.parse_error("Bad now argument.");
b137461999-08-26Martin Nilsson  } }
2d94ef1999-07-19Martin Nilsson  mapping now = localtime(unix_now); mapping time_args = ([]); time_args->year=now->year; time_args->mon=now->mon; time_args->mday=now->mday; time_args->hour=now->hour; time_args->min=now->min; time_args->sec=now->sec; if(m->year) {
1cbdd51997-10-25Per Hedbor  time_args->year = ((int)m->year-1900); if(time_args->year < -1800) time_args->year += 1900;
2d94ef1999-07-19Martin Nilsson  tprec="year"; time_args=clear_less_significant(time_args, "year"); } if(m->iso) {
c9e6c92000-02-16Per Hedbor  if(sscanf(m->iso, "%d-%d-%d",
2d94ef1999-07-19Martin Nilsson  time_args->year, time_args->mon, time_args->mday)==3 || sscanf(m->iso, "%4d%2d%2d",
b137461999-08-26Martin Nilsson  time_args->year, time_args->mon, time_args->mday)==3 || sscanf(m->iso, "%d-%s-%d", time_args->year, time_args->mon, time_args->mday) == 3) { if (stringp(time_args->mon)) time_args->mon = ([ "jan": 1, "feb": 2, "mar": 3, "apr": 4, "may": 5, "jun": 6, "jul": 7, "aug": 8, "sep": 9, "oct": 10, "nov": 11, "dec": 12 ]) [lower_case(sprintf("%s", time_args->mon))[0..2]];
2d94ef1999-07-19Martin Nilsson  time_args=clear_less_significant(time_args, "day"); tprec="day";
1cbdd51997-10-25Per Hedbor  time_args->mon--; if(time_args->year>1900) time_args->year-=1900; }
2d94ef1999-07-19Martin Nilsson  } if(m->month) {
1cbdd51997-10-25Per Hedbor  if(!(int)m->month) m->month = find_a_month(m->month)+1;
2d94ef1999-07-19Martin Nilsson  tprec="month";
1cbdd51997-10-25Per Hedbor  time_args->mon = (int)m->month-1;
2d94ef1999-07-19Martin Nilsson  if(time_args->mon!=now->mon) time_args=clear_less_significant(time_args, "mon"); } if(m->day) {
1cbdd51997-10-25Per Hedbor  if(!(int)m->day) m->day = find_a_day(m->day);
2d94ef1999-07-19Martin Nilsson  tprec="day";
1cbdd51997-10-25Per Hedbor  time_args->wday = (int)m->day-1;
2d94ef1999-07-19Martin Nilsson  if(time_args->wday!=now->wday) time_args=clear_less_significant(time_args, "day"); } if(m->mday) { tprec="day"; time_args->mday = (int)m->mday; if(time_args->mday!=now->mday) time_args=clear_less_significant(time_args, "day"); } if(m->hour) { tprec="hour"; time_args->hour = (int)m->hour; if(time_args->hour!=now->hour) time_args=clear_less_significant(time_args, "hour"); } if(m->minute) { tprec="minute"; time_args->min = (int)m->minute; if(time_args->min!=now->min) time_args=clear_less_significant(time_args, "min"); } if(m->second) { tprec="second"; time_args->sec = (int)m->second;
1cbdd51997-10-25Per Hedbor  }
2d94ef1999-07-19Martin Nilsson  if(time_args->mon < now->mon && unset_from(m,"mon")) time_args->year++; else if(time_args->mday < now->mday && unset_from(m,"day")) time_args->mon++; else if(time_args->hour < now->hour && unset_from(m,"hour")) time_args->mday++; else if(time_args->min < now->min && unset_from(m,"min")) time_args->hour++; else if(time_args->sec < now->sec && unset_from(m,"sec")) time_args->min++; if(m->event) {
6cabd12000-11-02Martin Nilsson  switch(m_delete(m, "event")) {
2d94ef1999-07-19Martin Nilsson  case "christmas-eve": time_args->mday=24; time_args->mon=11; tprec="day"; break; case "christmas": case "christmas-day": time_args->mday=25; time_args->mon=11; tprec="day"; break; case "julian-easter": mapping easter=set_to_julian_easter(time_args->year+1900); if(easter->mon-1 < time_args->mon || (easter->mon-1 == time_args->mon && easter->day < time_args->day)) easter=set_to_julian_easter(++(time_args->year)+1900); time_args->mon=easter->mon-1; time_args->mday=easter->day; time_args=clear_less_significant(time_args, "day"); tprec="day"; break; case "easter": case "gregorian-easter":
02a63f2000-09-05Per Hedbor  easter=set_to_gregorian_easter(time_args->year+1900);
2d94ef1999-07-19Martin Nilsson  if(easter->mon-1 < time_args->mon || (easter->mon-1 == time_args->mon && easter->day < time_args->day)) easter=set_to_gregorian_easter(++(time_args->year)+1900); time_args->mon=easter->mon-1; time_args->mday=easter->day; tprec="day"; break; }
1cbdd51997-10-25Per Hedbor  }
2d94ef1999-07-19Martin Nilsson  int prec; if(m->prec) tprec = m->prec;
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson  switch(tprec)
1cbdd51997-10-25Per Hedbor  {
2d94ef1999-07-19Martin Nilsson  case "year": prec=(int)(3600*24*days_per_year); break; case "month": prec=(int)(3600*24*(days_per_year/12)); break; case "week": prec=3600*24*7; break; case "day": prec=3600*24; break; case "hour": prec=3600; break; case "minute": prec=60; break;
6cabd12000-11-02Martin Nilsson  default: prec=(int)m->prec || 1;
1cbdd51997-10-25Per Hedbor  }
2d94ef1999-07-19Martin Nilsson  int when;
6cabd12000-11-02Martin Nilsson  if(catch( when = mktime(time_args) ))
5d3d502000-02-24Martin Nilsson  RXML.run_error("Resulted in an invalid time.");
2d94ef1999-07-19Martin Nilsson 
9ef5e01998-07-05Henrik Grubbström (Grubba)  if(!zero_type(time_args->wday)) {
b137461999-08-26Martin Nilsson  int wen=when;
2d94ef1999-07-19Martin Nilsson  when=weekday_handler(when, time_args);
9ef5e01998-07-05Henrik Grubbström (Grubba)  }
2d94ef1999-07-19Martin Nilsson  //FIXME: Clear less significant
6cabd12000-11-02Martin Nilsson  if(m->next && when==unix_now) {
2d94ef1999-07-19Martin Nilsson  if(m->month && unset_from(m,"mon")) time_args->year++; if(m->mday && unset_from(m,"day")) time_args->mon++; if(m->day && unset_from(m,"wday")) time_args->mday+=6; if(m->hour && unset_from(m,"hour")) time_args->mday++; if(m->minute && unset_from(m,"min")) time_args->hour++; if(m->second && unset_from(m,"sec")) time_args->sec++;
6cabd12000-11-02Martin Nilsson  if(catch( when = mktime(time_args) ))
5d3d502000-02-24Martin Nilsson  RXML.run_error("Resulted in an invalid time.");
2d94ef1999-07-19Martin Nilsson  //if(!zero_type(time_args->wday)) { // when=weekday_handler(when, time_args); //}
6cabd12000-11-02Martin Nilsson  m_delete(m, "next");
1cbdd51997-10-25Per Hedbor  }
2d94ef1999-07-19Martin Nilsson  foreach(({"second","minute","hour","mday","day","month","year","iso","prec"}), string tmp) { m_delete(m, tmp);
1cbdd51997-10-25Per Hedbor  }
1a73582000-04-30Martin Nilsson  when+=Roxen.time_dequantifier(m);
2d94ef1999-07-19Martin Nilsson  int delay = when-unix_now; if(m->since) delay = -delay;
1cbdd51997-10-25Per Hedbor 
2d94ef1999-07-19Martin Nilsson  if(m->round=="up") { delay=((delay/prec)+(delay?1:0))*prec; when=((when/prec)+(delay?1:0))*prec;
6eac091998-07-18Fredrik Hübinette (Hubbe)  }
2d94ef1999-07-19Martin Nilsson 
6cabd12000-11-02Martin Nilsson  switch(m_delete(m, "display")) {
2d94ef1999-07-19Martin Nilsson  case "when":
1a73582000-04-30Martin Nilsson  return Roxen.tagtime(when, m, id, language);
2d94ef1999-07-19Martin Nilsson  case "combined": delay-=delay%prec; return time_period(delay, prec); case "dogyears":
6cabd12000-11-02Martin Nilsson  // FIXME: 7 per year the first two years, then 5 per year. Perhaps.
2d94ef1999-07-19Martin Nilsson  return sprintf("%1.1f",(delay/(3600*24*days_per_year/7))); case "years":
de5c3c2000-01-23Martin Nilsson  return show_number((int)(delay/(3600*24*days_per_year)), m, id);
2d94ef1999-07-19Martin Nilsson  case "months":
de5c3c2000-01-23Martin Nilsson  return show_number((int)(delay/((3600*24*days_per_year)/12)), m, id);
2d94ef1999-07-19Martin Nilsson  case "weeks":
de5c3c2000-01-23Martin Nilsson  return show_number(delay/(3600*24*7), m, id);
2d94ef1999-07-19Martin Nilsson  case "days":
de5c3c2000-01-23Martin Nilsson  return show_number(delay/(3600*24), m, id);
2d94ef1999-07-19Martin Nilsson  case "hours":
de5c3c2000-01-23Martin Nilsson  return show_number(delay/3600, m, id);
2d94ef1999-07-19Martin Nilsson 
2e5bbe1999-08-02Martin Nilsson  case "beats":
de5c3c2000-01-23Martin Nilsson  return "@"+show_number(delay/(3600*24/1000), m, id);
2e5bbe1999-08-02Martin Nilsson 
2d94ef1999-07-19Martin Nilsson  case "minutes":
de5c3c2000-01-23Martin Nilsson  return show_number(delay/60, m, id);
2d94ef1999-07-19Martin Nilsson  case "seconds":
de5c3c2000-01-23Martin Nilsson  return show_number(delay, m, id);
2d94ef1999-07-19Martin Nilsson  case "boolean": return (string)((when/prec) == (mktime(now)/prec)); case "debug": string ret="<pre>Debug.\n\ntime_args.\n"; foreach(indices(time_args), string tmp) ret+=tmp+": "+time_args[tmp]+"\n"; ret+="\nnow.\n"; foreach(indices(now), string tmp) ret+=tmp+": "+now[tmp]+"\n"; ret+="\nunix_now: "+unix_now+"\n when: "+when+"\n delay: "+delay+"\n\nLeft on arglist.\n"; foreach(indices(m), string tmp) ret+=tmp+": "+m[tmp]+"\n"; return ret+"</pre>\n";
6eac091998-07-18Fredrik Hübinette (Hubbe)  }
2d94ef1999-07-19Martin Nilsson  //FIXME: L10N if(tprec) return delay/prec+" "+tprec+(delay/prec>1?"s":""); return "I don't think I understood that, but I think you want to count to "+
1a73582000-04-30Martin Nilsson  Roxen.tagtime(when, m, id, language)+" to which it is "+when+" seconds. Write &lt;countdown"
2d94ef1999-07-19Martin Nilsson  " help&gt; to get an idea of what you ougt to write.";
1cbdd51997-10-25Per Hedbor }