1<?php
2/**
3 * DokuWiki Plugin relativetimehelper (Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Michael Große <dokuwiki@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class helper_plugin_relativetimehelper extends DokuWiki_Plugin {
13
14    const SECONDS_PER_YEAR = 31536000;
15    const SECONDS_PER_MONTH = 2635200;
16    const SECONDS_PER_WEEK = 604800;
17    const SECONDS_PER_DAY = 86400;
18    const SECONDS_PER_HOUR = 3600;
19    const SECONDS_PER_MINUTE = 60;
20
21    /**
22     * @param int $timestamp
23     * @param int $depth how fine the granularity should be
24     * @param int $now reference timestamp, defaults to time()
25     * @return string
26     */
27    public function getRelativeTimeString($timestamp, $depth = 2, $now = null) {
28        if (!$now) {
29            $now = time();
30        }
31        $timediff = abs($now - $timestamp);
32        $parts = array();
33        $seconds = $timediff % $this::SECONDS_PER_MINUTE;
34        if ($seconds != 0) {
35            if ($seconds == 1) {
36                $parts[] = sprintf($this->getLang('second'), 1);
37            } else {
38                $parts[] = sprintf($this->getLang('seconds'), $seconds);
39            }
40            $timediff -= $seconds;
41        } else {
42            $parts[] = null;
43        }
44
45        $minuts = ($timediff % $this::SECONDS_PER_HOUR) / $this::SECONDS_PER_MINUTE;
46        if ($minuts != 0) {
47            if ($minuts == 1) {
48                array_unshift($parts, sprintf($this->getLang('minut'), 1));
49            } else {
50                array_unshift($parts, sprintf($this->getLang('minuts'), $minuts));
51            }
52            $timediff -= $timediff % $this::SECONDS_PER_HOUR;
53        } elseif ($timediff) {
54            array_unshift($parts, null);
55        }
56
57        $hours = ($timediff % $this::SECONDS_PER_DAY) / $this::SECONDS_PER_HOUR;;
58        if ($hours != 0) {
59            if ($hours == 1) {
60                array_unshift($parts, sprintf($this->getLang('hour'), 1));
61            } else {
62                array_unshift($parts, sprintf($this->getLang('hours'), $hours));
63            }
64            $timediff -= $timediff % $this::SECONDS_PER_DAY;
65        } elseif ($timediff) {
66            array_unshift($parts, null);
67        }
68
69        $days = ($timediff % $this::SECONDS_PER_WEEK) / $this::SECONDS_PER_DAY;;
70        if ($days != 0) {
71            if ($days == 1) {
72                array_unshift($parts, sprintf($this->getLang('day'), 1));
73            } else {
74                array_unshift($parts, sprintf($this->getLang('days'), $days));
75            }
76            $timediff -= $timediff % $this::SECONDS_PER_WEEK;
77        } elseif ($timediff) {
78            array_unshift($parts, null);
79        }
80
81        $weeks = $timediff / $this::SECONDS_PER_WEEK; // todo extend to cover months and years by date-calculation
82        if ($weeks != 0) {
83            if ($weeks == 1) {
84                array_unshift($parts, sprintf($this->getLang('week'), 1));
85            } else {
86                array_unshift($parts, sprintf($this->getLang('weeks'), $weeks));
87            }
88        } elseif ($timediff) {
89            array_unshift($parts, null);
90        }
91
92        while (count($parts) > $depth) {
93            array_pop($parts);
94        }
95
96        $parts = array_filter($parts);
97
98        if (count($parts) == 1) {
99            $relTime = $parts[0];
100        } else {
101            $lastPart = array_pop($parts);
102            $relTime = join(', ', $parts) . ' ' . $this->getLang('and') . ' ' . $lastPart;
103        }
104        if ($now - $timestamp < 0) {
105            return sprintf($this->getLang('in future'), $relTime);
106        }
107        return sprintf($this->getLang('in past'), $relTime);
108    }
109
110    protected function round($number, $rounding){
111        if ($rounding == 'ceil') {
112            return ceil($number);
113        }
114        if ($rounding == 'floor') {
115            return floor($number);
116        }
117        return round($number);
118    }
119
120}
121
122// vim:ts=4:sw=4:et:
123