summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Database.php5
-rw-r--r--app/Functions/FunctionsDate.php58
-rw-r--r--app/GedcomRecord.php4
-rw-r--r--app/Http/Controllers/Admin/UsersController.php6
-rw-r--r--app/I18N.php31
-rw-r--r--app/Module/FamilyTreeNewsModule.php10
-rw-r--r--app/Module/HtmlBlockModule.php14
-rw-r--r--app/Module/ReviewChangesModule.php10
-rw-r--r--app/Module/UserJournalModule.php10
-rw-r--r--app/Module/UserMessagesModule.php12
-rw-r--r--app/Services/HousekeepingService.php9
-rw-r--r--app/Statistics/Repository/BrowserRepository.php15
-rw-r--r--app/Statistics/Repository/ServerRepository.php22
-rw-r--r--app/Timestamp.php49
-rw-r--r--index.php20
-rw-r--r--resources/views/modules/gedcom_news/list.phtml3
-rw-r--r--resources/views/modules/user_blog/list.phtml3
-rw-r--r--resources/views/pending-changes-page.phtml3
18 files changed, 107 insertions, 177 deletions
diff --git a/app/Database.php b/app/Database.php
index 0d4ab76468..f6cd39a4fb 100644
--- a/app/Database.php
+++ b/app/Database.php
@@ -50,10 +50,11 @@ class Database
'password' => $config['dbpass'],
'prefix' => $config['tblpfx'],
'prefix_indexes' => true,
+ // For MySQL
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
+ 'timezone' => '+00:00',
'engine' => 'InnoDB',
- 'foreign_key_constraints' => true,
'modes' => [
'ANSI',
'STRICT_TRANS_TABLES',
@@ -61,6 +62,8 @@ class Database
'NO_ZERO_DATE',
'ERROR_FOR_DIVISION_BY_ZERO',
],
+ // For SQLite
+ 'foreign_key_constraints' => true,
]);
$capsule->setAsGlobal();
diff --git a/app/Functions/FunctionsDate.php b/app/Functions/FunctionsDate.php
index f6a3c98dec..137b84a751 100644
--- a/app/Functions/FunctionsDate.php
+++ b/app/Functions/FunctionsDate.php
@@ -69,64 +69,6 @@ class FunctionsDate
}
/**
- * Convert a unix timestamp into a formatted date-time value, for logs, etc.
- * Don't attempt to convert into other calendars, as not all days start at
- * midnight, and we can only get it wrong.
- *
- * @param int $time
- *
- * @return string
- */
- public static function formatTimestamp(int $time): string
- {
- $time += WT_TIMESTAMP_OFFSET;
-
- $time_fmt = I18N::timeFormat();
- // PHP::date() doesn't do I18N. Do it ourselves....
- preg_match_all('/%[^%]/', $time_fmt, $matches);
- foreach ($matches[0] as $match) {
- switch ($match) {
- case '%a':
- $t = gmdate('His', $time);
- if ($t == '000000') {
- /* I18N: time format “%a” - exactly 00:00:00 */
- $time_fmt = str_replace($match, I18N::translate('midnight'), $time_fmt);
- } elseif ($t < '120000') {
- /* I18N: time format “%a” - between 00:00:01 and 11:59:59 */
- $time_fmt = str_replace($match, I18N::translate('a.m.'), $time_fmt);
- } elseif ($t == '120000') {
- /* I18N: time format “%a” - exactly 12:00:00 */
- $time_fmt = str_replace($match, I18N::translate('noon'), $time_fmt);
- } else {
- /* I18N: time format “%a” - between 12:00:01 and 23:59:59 */
- $time_fmt = str_replace($match, I18N::translate('p.m.'), $time_fmt);
- }
- break;
- case '%A':
- $t = gmdate('His', $time);
- if ($t == '000000') {
- /* I18N: time format “%A” - exactly 00:00:00 */
- $time_fmt = str_replace($match, I18N::translate('Midnight'), $time_fmt);
- } elseif ($t < '120000') {
- /* I18N: time format “%A” - between 00:00:01 and 11:59:59 */
- $time_fmt = str_replace($match, I18N::translate('A.M.'), $time_fmt);
- } elseif ($t == '120000') {
- /* I18N: time format “%A” - exactly 12:00:00 */
- $time_fmt = str_replace($match, I18N::translate('Noon'), $time_fmt);
- } else {
- /* I18N: time format “%A” - between 12:00:01 and 23:59:59 */
- $time_fmt = str_replace($match, I18N::translate('P.M.'), $time_fmt);
- }
- break;
- default:
- $time_fmt = str_replace($match, I18N::digits(gmdate(substr($match, -1), $time)), $time_fmt);
- }
- }
-
- return self::timestampToGedcomDate($time)->display() . '<span class="date"> - ' . $time_fmt . '</span>';
- }
-
- /**
* Convert a unix-style timestamp into a Date object
*
* @param int $time
diff --git a/app/GedcomRecord.php b/app/GedcomRecord.php
index 3eabde397e..7fd96385b9 100644
--- a/app/GedcomRecord.php
+++ b/app/GedcomRecord.php
@@ -17,10 +17,10 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees;
+use Carbon\Carbon;
use Closure;
use Exception;
use Fisharebest\Webtrees\Functions\Functions;
-use Fisharebest\Webtrees\Functions\FunctionsDate;
use Fisharebest\Webtrees\Functions\FunctionsImport;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
use Illuminate\Database\Capsule\Manager as DB;
@@ -1123,7 +1123,7 @@ class GedcomRecord
return $t;
}
- return strip_tags(FunctionsDate::formatTimestamp($t));
+ return I18N::localTime(Carbon::createFromTimestamp($t));
}
// The record does not have a CHAN event
diff --git a/app/Http/Controllers/Admin/UsersController.php b/app/Http/Controllers/Admin/UsersController.php
index 15ab2fa15b..a1e12704c2 100644
--- a/app/Http/Controllers/Admin/UsersController.php
+++ b/app/Http/Controllers/Admin/UsersController.php
@@ -17,10 +17,10 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Http\Controllers\Admin;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Contracts\UserInterface;
use Fisharebest\Webtrees\FlashMessages;
-use Fisharebest\Webtrees\Functions\FunctionsDate;
use Fisharebest\Webtrees\Functions\FunctionsEdit;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Log;
@@ -239,9 +239,9 @@ class UsersController extends AbstractAdminController
e($row->email),
$installed_languages[$row->language] ?? $row->language,
$row->registered_at,
- $row->registered_at > 0 ? FunctionsDate::formatTimestamp((int) $row->registered_at) : '',
+ $row->registered_at > 0 ? I18N::localTime(Carbon::createFromTimestamp((int) $row->registered_at)) : '',
$row->active_at,
- $row->active_at > 0 ? FunctionsDate::formatTimestamp((int) $row->active_at) : I18N::translate('Never'),
+ $row->active_at > 0 ? I18N::localTime(Carbon::createFromTimestamp((int) $row->active_at)) : I18N::translate('Never'),
$row->verified ? I18N::translate('yes') : I18N::translate('no'),
$row->verified_by_admin ? I18N::translate('yes') : I18N::translate('no'),
];
diff --git a/app/I18N.php b/app/I18N.php
index 7ec5cb812c..c4bf8642f7 100644
--- a/app/I18N.php
+++ b/app/I18N.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees;
+use Carbon\Carbon;
use Collator;
use Exception;
use Fisharebest\Localization\Locale;
@@ -327,7 +328,6 @@ class I18N
/**
* Convert the digits 0-9 into the local script
- *
* Used for years, etc., where we do not want thousands-separators, decimals, etc.
*
* @param string|int $n
@@ -522,7 +522,6 @@ class I18N
/**
* Translate a number into the local representation.
- *
* e.g. 12345.67 becomes
* en: 12,345.67
* fr: 12 345,67
@@ -540,7 +539,6 @@ class I18N
/**
* Translate a fraction into a percentage.
- *
* e.g. 0.123 becomes
* en: 12.3%
* fr: 12,3 %
@@ -578,11 +576,8 @@ class I18N
/**
* UTF8 version of PHP::strrev()
- *
* Reverse RTL text for third-party libraries such as GD2 and googlechart.
- *
* These do not support UTF8 text direction, so we must mimic it for them.
- *
* Numbers are always rendered LTR, even in RTL text.
* The visual direction of characters such as parentheses should be reversed.
*
@@ -623,7 +618,6 @@ class I18N
/**
* Return the direction (ltr or rtl) for a given script
- *
* The PHP/intl library does not provde this information, so we need
* our own lookup table.
*
@@ -806,7 +800,6 @@ class I18N
/**
* Translate a string, and then substitute placeholders
- *
* echo I18N::translate('Hello World!');
* echo I18N::translate('The %s sat on the mat', 'cat');
*
@@ -839,4 +832,26 @@ class I18N
return sprintf($message, ...$args);
}
+
+ /**
+ * Display a timestamp in the user's local timezone.
+ *
+ * @param Carbon $timestamp
+ * @param string $format
+ * @param string $timezone
+ *
+ * @return string
+ */
+ public static function localTime(Carbon $timestamp, string $format = '', string $timezone = ''): string
+ {
+ $format = $format ?: strtr(self::dateFormat() . ' ' . self::timeFormat(), ['%' => '']);
+
+ $timezone = $timezone ?: Auth::user()->getPreference('TIMEZONE', Site::getPreference('TIMEZONE', 'UTC'));
+
+ $local_timestamp = $timestamp->copy();
+
+ $local_timestamp->tz = $timezone;
+
+ return $local_timestamp->format($format);
+ }
}
diff --git a/app/Module/FamilyTreeNewsModule.php b/app/Module/FamilyTreeNewsModule.php
index 2d165d485f..02d5a44b79 100644
--- a/app/Module/FamilyTreeNewsModule.php
+++ b/app/Module/FamilyTreeNewsModule.php
@@ -17,10 +17,12 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Module;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Tree;
use Illuminate\Database\Capsule\Manager as DB;
+use stdClass;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -70,8 +72,12 @@ class FamilyTreeNewsModule extends AbstractModule implements ModuleBlockInterfac
$articles = DB::table('news')
->where('gedcom_id', '=', $tree->id())
->orderByDesc('updated')
- ->select(['news_id', 'user_id', 'gedcom_id', DB::raw('UNIX_TIMESTAMP(updated) AS updated'), 'subject', 'body'])
- ->get();
+ ->get()
+ ->map(function (stdClass $row): stdClass {
+ $row->updated = new Carbon($row->updated);
+
+ return $row;
+ });
$content = view('modules/gedcom_news/list', [
'articles' => $articles,
diff --git a/app/Module/HtmlBlockModule.php b/app/Module/HtmlBlockModule.php
index 9246370099..fe8cc8456d 100644
--- a/app/Module/HtmlBlockModule.php
+++ b/app/Module/HtmlBlockModule.php
@@ -17,8 +17,8 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Module;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Auth;
-use Fisharebest\Webtrees\Functions\FunctionsDate;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Statistics;
use Fisharebest\Webtrees\Tree;
@@ -77,14 +77,14 @@ class HtmlBlockModule extends AbstractModule implements ModuleBlockInterface
return '';
}
- /*
- * Retrieve text, process embedded variables
- */
+ // Retrieve text, process embedded variables
$title = $statistics->embedTags($title);
$content = $statistics->embedTags($content);
- if ($show_timestamp === '1') {
- $content .= '<br>' . FunctionsDate::formatTimestamp((int) $this->getBlockSetting($block_id, 'timestamp', (string) WT_TIMESTAMP));
+ $block_timestamp = (int) $this->getBlockSetting($block_id, 'timestamp', (string) WT_TIMESTAMP);
+
+ if ($show_timestamp === '1' && $block_timestamp > 0) {
+ $content .= '<br>' . I18N::localTime(Carbon::createFromTimestamp($block_timestamp));
}
if ($ctype !== '') {
@@ -146,7 +146,7 @@ class HtmlBlockModule extends AbstractModule implements ModuleBlockInterface
$this->setBlockSetting($block_id, 'title', $request->get('title', ''));
$this->setBlockSetting($block_id, 'html', $request->get('html', ''));
$this->setBlockSetting($block_id, 'show_timestamp', $request->get('show_timestamp', ''));
- $this->setBlockSetting($block_id, 'timestamp', $request->get('timestamp', ''));
+ $this->setBlockSetting($block_id, 'timestamp', (string) Carbon::now()->timestamp);
$this->setBlockSetting($block_id, 'languages', implode(',', $languages));
}
diff --git a/app/Module/ReviewChangesModule.php b/app/Module/ReviewChangesModule.php
index 9e736459fc..68c147d188 100644
--- a/app/Module/ReviewChangesModule.php
+++ b/app/Module/ReviewChangesModule.php
@@ -17,8 +17,8 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Module;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Auth;
-use Fisharebest\Webtrees\Functions\FunctionsDate;
use Fisharebest\Webtrees\GedcomRecord;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Mail;
@@ -132,9 +132,11 @@ class ReviewChangesModule extends AbstractModule implements ModuleBlockInterface
$content .= '<a href="' . e(route('show-pending', ['ged' => $tree->name()])) . '">' . I18N::translate('There are pending changes for you to moderate.') . '</a><br>';
}
if ($sendmail === '1') {
- $last_email_timestamp = (int) Site::getPreference('LAST_CHANGE_EMAIL');
- $content .= I18N::translate('Last email reminder was sent ') . FunctionsDate::formatTimestamp($last_email_timestamp) . '<br>';
- $content .= I18N::translate('Next email reminder will be sent after ') . FunctionsDate::formatTimestamp($last_email_timestamp + 60 * 60 * 24 * $days) . '<br><br>';
+ $last_email_timestamp = Carbon::createFromTimestamp((int) Site::getPreference('LAST_CHANGE_EMAIL'));
+ $next_email_timestamp = $last_email_timestamp->copy()->addDays($days);
+
+ $content .= I18N::translate('Last email reminder was sent ') . I18N::localTime($last_email_timestamp) . '<br>';
+ $content .= I18N::translate('Next email reminder will be sent after ') . I18N::localTime($next_email_timestamp) . '<br><br>';
}
$content .= '<ul>';
diff --git a/app/Module/UserJournalModule.php b/app/Module/UserJournalModule.php
index eecc4a0f19..23b7d52c0a 100644
--- a/app/Module/UserJournalModule.php
+++ b/app/Module/UserJournalModule.php
@@ -17,10 +17,12 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Module;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Tree;
use Illuminate\Database\Capsule\Manager as DB;
+use stdClass;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -70,8 +72,12 @@ class UserJournalModule extends AbstractModule implements ModuleBlockInterface
$articles = DB::table('news')
->where('user_id', '=', Auth::id())
->orderByDesc('updated')
- ->select(['news_id', 'user_id', 'gedcom_id', DB::raw('UNIX_TIMESTAMP(updated) AS updated'), 'subject', 'body'])
- ->get();
+ ->get()
+ ->map(function (stdClass $row): stdClass {
+ $row->updated = new Carbon($row->updated);
+
+ return $row;
+ });
$content = view('modules/user_blog/list', [
'articles' => $articles,
diff --git a/app/Module/UserMessagesModule.php b/app/Module/UserMessagesModule.php
index ef8aeeb5f5..12c3efb537 100644
--- a/app/Module/UserMessagesModule.php
+++ b/app/Module/UserMessagesModule.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Module;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Contracts\UserInterface;
use Fisharebest\Webtrees\Filter;
@@ -26,6 +27,7 @@ use Fisharebest\Webtrees\Services\UserService;
use Fisharebest\Webtrees\Tree;
use Fisharebest\Webtrees\User;
use Illuminate\Database\Capsule\Manager as DB;
+use stdClass;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -115,8 +117,12 @@ class UserMessagesModule extends AbstractModule implements ModuleBlockInterface
$messages = DB::table('message')
->where('user_id', '=', Auth::id())
->orderByDesc('message_id')
- ->select(['message_id', 'sender', 'subject', 'body', DB::raw('UNIX_TIMESTAMP(created) AS created')])
- ->get();
+ ->get()
+ ->map(function (stdClass $row): stdClass {
+ $row->created = new Carbon($row->created);
+
+ return $row;
+ });
$users = $this->user_service->all()->filter(function (UserInterface $user) use ($tree): bool {
$public_tree = $tree->getPreference('REQUIRE_AUTHENTICATION') !== '1';
@@ -166,7 +172,7 @@ class UserMessagesModule extends AbstractModule implements ModuleBlockInterface
$content .= '<tr>';
$content .= '<td class="list_value_wrap center"><input type="checkbox" name="message_id[]" value="' . $message->message_id . '" id="cb_message' . $message->message_id . '"></td>';
$content .= '<td class="list_value_wrap"><a href="#" onclick="return expand_layer(\'message' . $message->message_id . '\');"><i id="message' . $message->message_id . '_img" class="icon-plus"></i> <b dir="auto">' . e($message->subject) . '</b></a></td>';
- $content .= '<td class="list_value_wrap">' . FunctionsDate::formatTimestamp((int) $message->created) . '</td>';
+ $content .= '<td class="list_value_wrap">' . I18N::localTime($message->created) . '</td>';
$content .= '<td class="list_value_wrap">';
$user = $this->user_service->findByIdentifier($message->sender);
diff --git a/app/Services/HousekeepingService.php b/app/Services/HousekeepingService.php
index 5ae89904a4..a59db975c6 100644
--- a/app/Services/HousekeepingService.php
+++ b/app/Services/HousekeepingService.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Services;
+use Carbon\Carbon;
use Exception;
use Illuminate\Database\Capsule\Manager as DB;
use League\Flysystem\Filesystem;
@@ -428,9 +429,11 @@ class HousekeepingService
*/
public function deleteOldLogs(int $max_age_in_seconds)
{
+ $timestamp = Carbon::now()->subSeconds($max_age_in_seconds);
+
DB::table('log')
->whereIn('log_type', ['error', 'media'])
- ->whereRaw('log_time < FROM_UNIXTIME(?)', [WT_TIMESTAMP - $max_age_in_seconds])
+ ->where('log_time', '<', $timestamp)
->delete();
}
@@ -441,8 +444,10 @@ class HousekeepingService
*/
public function deleteOldSessions(int $max_age_in_seconds)
{
+ $timestamp = Carbon::now()->subSeconds($max_age_in_seconds);
+
DB::table('session')
- ->whereRaw('session_time < FROM_UNIXTIME(?)', [WT_TIMESTAMP - $max_age_in_seconds])
+ ->where('session_time', '<', $timestamp)
->delete();
}
diff --git a/app/Statistics/Repository/BrowserRepository.php b/app/Statistics/Repository/BrowserRepository.php
index cfc4e3c275..443cbf36aa 100644
--- a/app/Statistics/Repository/BrowserRepository.php
+++ b/app/Statistics/Repository/BrowserRepository.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Statistics\Repository;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Functions\FunctionsDate;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Statistics\Repository\Interfaces\BrowserRepositoryInterface;
@@ -31,8 +32,9 @@ class BrowserRepository implements BrowserRepositoryInterface
*/
public function browserDate(): string
{
- // TODO: Duplicates ServerRepository::serverDate
- return FunctionsDate::timestampToGedcomDate((int) WT_TIMESTAMP)->display();
+ $format = strtr(I18N::dateFormat(), ['%' => '']);
+
+ return I18N::localTime(Carbon::now(), $format);
}
/**
@@ -40,10 +42,9 @@ class BrowserRepository implements BrowserRepositoryInterface
*/
public function browserTime(): string
{
- return date(
- str_replace('%', '', I18N::timeFormat()),
- WT_TIMESTAMP + WT_TIMESTAMP_OFFSET
- );
+ $format = strtr(I18N::timeFormat(), ['%' => '']);
+
+ return I18N::localTime(Carbon::now(), $format);
}
/**
@@ -51,6 +52,6 @@ class BrowserRepository implements BrowserRepositoryInterface
*/
public function browserTimezone(): string
{
- return date('T', WT_TIMESTAMP + WT_TIMESTAMP_OFFSET);
+ return I18N::localTime(Carbon::now(), 'T');
}
}
diff --git a/app/Statistics/Repository/ServerRepository.php b/app/Statistics/Repository/ServerRepository.php
index 8d39987415..3301d418d5 100644
--- a/app/Statistics/Repository/ServerRepository.php
+++ b/app/Statistics/Repository/ServerRepository.php
@@ -17,7 +17,10 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Statistics\Repository;
+use Carbon\Carbon;
use Fisharebest\Webtrees\Functions\FunctionsDate;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Site;
use Fisharebest\Webtrees\Statistics\Repository\Interfaces\ServerRepositoryInterface;
/**
@@ -30,8 +33,10 @@ class ServerRepository implements ServerRepositoryInterface
*/
public function serverDate(): string
{
- // TODO: Duplicates BrowserRepository::browserDate
- return FunctionsDate::timestampToGedcomDate((int) WT_TIMESTAMP)->display();
+ $format = strtr(I18N::dateFormat(), ['%' => '']);
+ $timezone = Site::getPreference('TIMEZONE', 'UTC');
+
+ return I18N::localTime(Carbon::now(), $format, $timezone);
}
/**
@@ -39,7 +44,10 @@ class ServerRepository implements ServerRepositoryInterface
*/
public function serverTime(): string
{
- return date('g:i a');
+ $format = strtr(I18N::timeFormat(), ['%' => '']);
+ $timezone = Site::getPreference('TIMEZONE', 'UTC');
+
+ return I18N::localTime(Carbon::now(), $format, $timezone);
}
/**
@@ -47,7 +55,9 @@ class ServerRepository implements ServerRepositoryInterface
*/
public function serverTime24(): string
{
- return date('G:i');
+ $timezone = Site::getPreference('TIMEZONE', 'UTC');
+
+ return I18N::localTime(Carbon::now(), 'G:i', $timezone);
}
/**
@@ -55,6 +65,8 @@ class ServerRepository implements ServerRepositoryInterface
*/
public function serverTimezone(): string
{
- return date('T');
+ $timezone = Site::getPreference('TIMEZONE', 'UTC');
+
+ return I18N::localTime(Carbon::now(), 'T', $timezone);
}
}
diff --git a/app/Timestamp.php b/app/Timestamp.php
deleted file mode 100644
index 7459d26b92..0000000000
--- a/app/Timestamp.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-/**
- * webtrees: online genealogy
- * Copyright (C) 2019 webtrees development team
- * 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/>.
- */
-declare(strict_types=1);
-
-namespace Fisharebest\Webtrees;
-
-/**
- * Timestamps
- */
-class Timestamp
-{
- /** @var int UNIX style timestamp */
- private $time;
-
- /**
- * Create a timestamp.
- *
- * @param int $time Number of seconds since 1 Jan 1970
- */
- public function __construct(int $time = WT_TIMESTAMP)
- {
- $this->time = $time;
- }
-
- /**
- * Convert a timezone into a date.
- *
- * @param int $tz_offset
- *
- * @return Date
- */
- public function toDate(int $tz_offset = WT_TIMESTAMP_OFFSET): Date
- {
- return new Date(strtoupper(gmdate('j M Y', $this->time + $tz_offset)));
- }
-}
diff --git a/index.php b/index.php
index fc44be72a0..84545ece73 100644
--- a/index.php
+++ b/index.php
@@ -163,24 +163,8 @@ if ($max_execution_time !== '' && strpos(ini_get('disable_functions'), 'set_time
// Sessions
Session::start();
-// Note that the database/webservers may not be synchronised, so use DB time throughout.
-define('WT_TIMESTAMP', Carbon::now()->timestamp);
-
-// Users get their own time-zone. Visitors get the site time-zone.
-try {
- if (Auth::check()) {
- date_default_timezone_set(Auth::user()->getPreference('TIMEZONE'));
- } else {
- date_default_timezone_set(Site::getPreference('TIMEZONE'));
- }
-} catch (ErrorException $exception) {
- // Server upgrades and migrations can leave us with invalid timezone settings.
- date_default_timezone_set('UTC');
-}
-
-define('WT_TIMESTAMP_OFFSET', (new DateTime('now'))->getOffset());
-
-define('WT_CLIENT_JD', 2440588 + intdiv(WT_TIMESTAMP + WT_TIMESTAMP_OFFSET, 86400));
+define('WT_TIMESTAMP', Carbon::now('UTC')->timestamp);
+define('WT_CLIENT_JD', 2440588 + intdiv(WT_TIMESTAMP, 86400));
// Update the last-login time no more than once a minute
if (WT_TIMESTAMP - Session::get('activity_time') >= 60) {
diff --git a/resources/views/modules/gedcom_news/list.phtml b/resources/views/modules/gedcom_news/list.phtml
index 435e28f7c5..2ff4afd503 100644
--- a/resources/views/modules/gedcom_news/list.phtml
+++ b/resources/views/modules/gedcom_news/list.phtml
@@ -1,5 +1,4 @@
<?php use Fisharebest\Webtrees\Auth; ?>
-<?php use Fisharebest\Webtrees\Functions\FunctionsDate; ?>
<?php use Fisharebest\Webtrees\I18N; ?>
<?php if (empty($articles)) : ?>
@@ -17,7 +16,7 @@
<div class="news_box">
<div class="news_title"><?= e($article->subject) ?></div>
- <div class="news_date"><?= FunctionsDate::formatTimestamp($article->updated) ?></div>
+ <div class="news_date"><?= I18N::localTime($article->updated) ?></div>
<div style="white-space: pre-wrap"><?= e($article->body) ?></div>
<?php if (Auth::isManager($tree)) : ?>
diff --git a/resources/views/modules/user_blog/list.phtml b/resources/views/modules/user_blog/list.phtml
index e60e26f8a7..4a05888a5d 100644
--- a/resources/views/modules/user_blog/list.phtml
+++ b/resources/views/modules/user_blog/list.phtml
@@ -1,5 +1,4 @@
<?php use Fisharebest\Webtrees\Auth; ?>
-<?php use Fisharebest\Webtrees\Functions\FunctionsDate; ?>
<?php use Fisharebest\Webtrees\I18N; ?>
<?php if (empty($articles)) : ?>
@@ -17,7 +16,7 @@
<div class="news_box">
<div class="news_title"><?= e($article->subject) ?></div>
- <div class="news_date"><?= FunctionsDate::formatTimestamp($article->updated) ?></div>
+ <div class="news_date"><?= I18N::localTime($article->updated) ?></div>
<div style="white-space: pre-wrap"><?= e($article->body) ?></div>
<?php if (Auth::isManager($tree)) : ?>
diff --git a/resources/views/pending-changes-page.phtml b/resources/views/pending-changes-page.phtml
index 1188b6ed27..95f4bee246 100644
--- a/resources/views/pending-changes-page.phtml
+++ b/resources/views/pending-changes-page.phtml
@@ -1,4 +1,3 @@
-<?php use Fisharebest\Webtrees\Functions\FunctionsDate; ?>
<?php use Fisharebest\Webtrees\I18N; ?>
<?php use Fisharebest\Webtrees\Tree; ?>
@@ -78,7 +77,7 @@
</a>
</td>
<td>
- <?= FunctionsDate::formatTimestamp($record_change->change_time->timestamp) ?>
+ <?= I18N::localTime($record_change->change_time) ?>
</td>
<td>
<form action="<?= e(route('reject-pending', ['change_id' => $record_change->change_id, 'xref' => $record_change->xref, 'ged' => $record_change->gedcom_name, 'url' => $url])) ?>" method="POST">