diff --git a/includes/view/ShiftEntry_view.php b/includes/view/ShiftEntry_view.php
index fb63c45c..d3194e0f 100644
--- a/includes/view/ShiftEntry_view.php
+++ b/includes/view/ShiftEntry_view.php
@@ -1,5 +1,6 @@
format(__('Y-m-d H:i'));
return page_with_title(
ShiftEntry_create_title() . ': ' . $shift['name']
- . ' %c',
+ . ' %c',
[
Shift_view_header($shift, $room),
info(__('Do you want to sign up the following user for this shift?'), true),
@@ -116,9 +118,10 @@ function ShiftEntry_create_view_admin(
*/
function ShiftEntry_create_view_supporter($shift, Room $room, AngelType $angeltype, $signup_user, $users_select)
{
+ $start = Carbon::createFromTimestamp($shift['start'])->format(__('Y-m-d H:i'));
return page_with_title(
ShiftEntry_create_title() . ': ' . $shift['name']
- . ' %c',
+ . ' %c',
[
Shift_view_header($shift, $room),
info(sprintf(
@@ -144,9 +147,10 @@ function ShiftEntry_create_view_supporter($shift, Room $room, AngelType $angelty
*/
function ShiftEntry_create_view_user($shift, Room $room, AngelType $angeltype, $comment)
{
+ $start = Carbon::createFromTimestamp($shift['start'])->format(__('Y-m-d H:i'));
return page_with_title(
ShiftEntry_create_title() . ': ' . $shift['name']
- . ' %c',
+ . ' %c',
[
Shift_view_header($shift, $room),
info(sprintf(__('Do you want to sign up for this shift as %s?'), AngelType_name_render($angeltype)), true),
diff --git a/includes/view/Shifts_view.php b/includes/view/Shifts_view.php
index 35416e9d..ce8b1fdc 100644
--- a/includes/view/Shifts_view.php
+++ b/includes/view/Shifts_view.php
@@ -1,5 +1,6 @@
format(__('Y-m-d H:i'));
+
return page_with_title(
- $shift['name'] . ' %c',
+ $shift['name'] . ' %c',
$content
);
}
diff --git a/includes/view/User_view.php b/includes/view/User_view.php
index f03407f8..ed80bee6 100644
--- a/includes/view/User_view.php
+++ b/includes/view/User_view.php
@@ -189,25 +189,28 @@ function User_shift_state_render($user)
$nextShift = array_shift($upcoming_shifts);
+ $start = Carbon::createFromTimestamp($nextShift['start'])->format(__('Y-m-d H:i'));
+
if ($nextShift['start'] > time()) {
if ($nextShift['start'] - time() > 3600) {
- return ''
+ return ''
. __('Next shift %c')
. '';
}
- return ''
+ return ''
. __('Next shift %c')
. '';
}
$halfway = ($nextShift['start'] + $nextShift['end']) / 2;
if (time() < $halfway) {
- return ''
+ return ''
. __('Shift started %c')
. '';
}
- return ''
+ $end = Carbon::createFromTimestamp($nextShift['end'])->format(__('Y-m-d H:i'));
+ return ''
. __('Shift ends %c')
. '';
}
@@ -224,7 +227,9 @@ function User_last_shift_render($user)
}
$lastShift = array_shift($last_shifts);
- return ''
+ $end = Carbon::createFromTimestamp($lastShift['end'])->format(__('Y-m-d H:i'));
+
+ return ''
. __('Shift ended %c')
. '';
}
diff --git a/resources/assets/js/countdown.js b/resources/assets/js/countdown.js
index cf47aaa2..48bfbbba 100644
--- a/resources/assets/js/countdown.js
+++ b/resources/assets/js/countdown.js
@@ -1,85 +1,47 @@
import { ready } from './ready';
-const lang = document.documentElement.getAttribute('lang');
-
-const templateFuture = 'in %value %unit';
-const templatePast = lang === 'en'
- ? '%value %unit ago'
- : 'vor %value %unit';
-
-const yearUnits = lang === 'en'
- ? ['year', 'years']
- : ['Jahr', 'Jahren'];
-
-const monthUnits = lang === 'en'
- ? ['month', 'months']
- : ['Monat', 'Monaten'];
-
-const dayUnits = lang === 'en'
- ? ['day', 'days']
- : ['Tag', 'Tagen'];
-
-const hourUnits = lang === 'en'
- ? ['hour', 'hours']
- : ['Stunde', 'Stunden'];
-
-const minuteUnits = lang === 'en'
- ? ['minute', 'minutes']
- : ['Minute', 'Minuten'];
-
-const secondUnits = lang === 'en'
- ? ['second', 'seconds']
- : ['Sekunde', 'Sekunden'];
-
-const nowString = lang === 'en' ? 'now' : 'jetzt';
-
-const secondsHour = 60 * 60;
-
-const timeFrames = [
- [365 * 24 * 60 * 60, yearUnits],
- [30 * 24 * 60 * 60, monthUnits],
- [24 * 60 * 60, dayUnits],
- [secondsHour, hourUnits],
- [60, minuteUnits],
- [1, secondUnits],
-];
-
-/**
- * @param {number} timestamp
- * @returns {string}
- */
-function formatFromNow(timestamp) {
- const now = Date.now() / 1000;
- const diff = Math.abs(timestamp - now);
- const ago = now > timestamp;
-
- for (const [duration, [singular, plural]] of timeFrames) {
- const value = diff < secondsHour
- ? Math.floor(diff / duration)
- : Math.round(diff / duration);
-
- if (value) {
- const template = ago ? templatePast : templateFuture;
- const unit = value === 1 ? singular : plural;
- return template
- .replace('%value', value)
- .replace('%unit', unit);
- }
- }
-
- return nowString;
-}
-
/**
* Initialises all countdown fields on the page.
*/
ready(() => {
+ const lang = document.documentElement.getAttribute('lang');
+
+ const rtf = new Intl.RelativeTimeFormat(lang, { numeric: 'auto' });
+
+ const timeFrames = [
+ [60 * 60 * 24 * 365, 'year'],
+ [60 * 60 * 24 * 30, 'month'],
+ [60 * 60 * 24 * 7, 'week'],
+ [60 * 60 * 24, 'day'],
+ [60 * 60, 'hour'],
+ [60, 'minute'],
+ [1, 'second'],
+ ];
+
+ /**
+ * @param {number} timestamp
+ * @returns {string}
+ */
+ function formatFromNow(timestamp) {
+ const now = Date.now() / 1000;
+ const diff = Math.round(timestamp - now);
+ const absValue = Math.abs(diff);
+
+ for (const [duration, unit] of timeFrames) {
+ if (absValue >= duration) {
+ return rtf.format(Math.round(diff / duration), unit);
+ }
+ }
+
+ return rtf.format(0, 'second');
+ }
+
document.querySelectorAll('[data-countdown-ts]').forEach((element) => {
const timestamp = Number(element.dataset.countdownTs);
- const template = element.innerHTML;
- element.innerHTML = template.replace('%c', formatFromNow(timestamp));
+ const template = element.textContent;
+ element.textContent = template.replace('%c', formatFromNow(timestamp));
setInterval(() => {
- element.innerHTML = template.replace('%c', formatFromNow(timestamp));
+ element.textContent = template.replace('%c', formatFromNow(timestamp));
}, 1000);
});
});
diff --git a/resources/views/pages/design.twig b/resources/views/pages/design.twig
index 6c43c65c..ad15d441 100644
--- a/resources/views/pages/design.twig
+++ b/resources/views/pages/design.twig
@@ -322,20 +322,20 @@
Countdowns
- - 30s: %c
- - 30m: %c
- - 59m: %c
- - 1h: %c
- - 1h 30m: %c
- - 1h 31m: %c
- - 2h: %c
- - 2d: %c
- - 3m: %c
- - 22y: %c
+ - 30s: %c
+ - 30m: %c
+ - 59m: %c
+ - 1h: %c
+ - 1h 30m: %c
+ - 1h 31m: %c
+ - 2h: %c
+ - 2d: %c
+ - 3m: %c
+ - 22y: %c
- - 30m ago: %c
- - 45m ago: %c
+ - 30m ago: %c
+ - 45m ago: %c
diff --git a/resources/views/pages/login.twig b/resources/views/pages/login.twig
index c7ee7b90..8da88ed5 100644
--- a/resources/views/pages/login.twig
+++ b/resources/views/pages/login.twig
@@ -21,7 +21,7 @@
{% if date > date() %}
{{ name }}
-
%c
+
%c
{{ date.format(__('Y-m-d')) }}
{% endif %}
diff --git a/src/Controllers/DesignController.php b/src/Controllers/DesignController.php
index 59c3156e..e52cd187 100644
--- a/src/Controllers/DesignController.php
+++ b/src/Controllers/DesignController.php
@@ -41,24 +41,26 @@ class DesignController extends BaseController
]));
$themes = $this->config->get('themes');
+ $date = new \DateTimeImmutable();
$data = [
- 'demo_user' => $demoUser,
- 'demo_user_2' => $demoUser2,
- 'themes' => $themes,
- 'bar_chart' => BarChart::render(...BarChart::generateChartDemoData(23)),
- 'timestamp30m' => time() + 30 * 60,
- 'timestamp59m' => time() + 59 * 60,
- 'timestamp1h' => time() + 1 * 60 * 60,
- 'timestamp1h30m' => time() + 90 * 60,
- 'timestamp1h31m' => time() + 91 * 60,
- 'timestamp2h' => time() + 2 * 60 * 60,
- 'timestamp2d' => time() + 2 * 24 * 60 * 60,
- 'timestamp3m' => time() + 3 * 30 * 24 * 60 * 60,
- 'timestamp22y' => time() + 22 * 365 * 24 * 60 * 60,
- 'timestamp30s' => time() + 30,
+ 'demo_user' => $demoUser,
+ 'demo_user_2' => $demoUser2,
+ 'themes' => $themes,
+ 'bar_chart' => BarChart::render(...BarChart::generateChartDemoData(23)),
- 'timestamp30mago' => time() - 30 * 60,
- 'timestamp45mago' => time() - 45 * 60,
+ 'timestamp30m' => $date->add(new \DateInterval('PT30M')),
+ 'timestamp59m' => $date->add(new \DateInterval('PT59M')),
+ 'timestamp1h' => $date->add(new \DateInterval('PT1H')),
+ 'timestamp1h30m' => $date->add(new \DateInterval('PT1H30M')),
+ 'timestamp1h31m' => $date->add(new \DateInterval('PT1H31M')),
+ 'timestamp2h' => $date->add(new \DateInterval('PT2H')),
+ 'timestamp2d' => $date->add(new \DateInterval('P2D')),
+ 'timestamp3m' => $date->add(new \DateInterval('P3M')),
+ 'timestamp22y' => $date->add(new \DateInterval('P22Y')),
+ 'timestamp30s' => $date->add(new \DateInterval('PT30S')),
+
+ 'timestamp30mago' => $date->sub(new \DateInterval('PT30M')),
+ 'timestamp45mago' => $date->sub(new \DateInterval('PT45M')),
];
return $this->response->withView(