diff --git a/controllers/SystemApiController.php b/controllers/SystemApiController.php index debadc9f..bd12d253 100644 --- a/controllers/SystemApiController.php +++ b/controllers/SystemApiController.php @@ -43,6 +43,30 @@ class SystemApiController extends BaseApiController return $this->ApiResponse($response, $this->getApplicationService()->GetSystemInfo()); } + public function GetSystemTime(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) + { + try + { + $offset = 0; + $params = $request->getQueryParams(); + if (isset($params['offset'])) + { + if (!filter_var($params['offset'], FILTER_VALIDATE_INT)) + { + throw new \Exception('Query parameter "offset" is not a valid integer'); + } + + $offset = $params['offset']; + } + + return $this->ApiResponse($response, $this->getApplicationService()->GetSystemTime($offset)); + } + catch (\Exception $ex) + { + return $this->GenericErrorResponse($response, $ex->getMessage()); + } + } + public function LogMissingLocalization(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) { if (GROCY_MODE === 'dev') diff --git a/grocy.openapi.json b/grocy.openapi.json index 2e231ede..5d786086 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -146,6 +146,41 @@ } } }, + "/system/time": { + "get": { + "summary": "Returns the current server time", + "tags": [ + "System" + ], + "parameters": [ + { + "$ref": "#/components/parameters/offsettime" + } + ], + "responses": { + "200": { + "description": "A TimeResponse object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimeResponse" + } + } + } + }, + "400": { + "description": "The operation was not successful", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error400" + } + } + } + } + } + } + }, "/system/log-missing-localization": { "post": { "summary": "Logs a missing localization string", @@ -5170,6 +5205,32 @@ } } }, + "TimeResponse": { + "type": "object", + "properties": { + "timezone": { + "type": "string" + }, + "time_local": { + "type": "string", + "format": "date-time" + }, + "time_local_sqlite3": { + "type": "string", + "format": "date-time" + }, + "time_utc": { + "type": "string", + "format": "date-time" + }, + "timestamp": { + "type": "integer" + }, + "offset": { + "type": "integer" + } + } + }, "UserSetting": { "type": "object", "properties": { @@ -5222,6 +5283,15 @@ "type": "integer" } }, + "offsettime": { + "in": "query", + "name": "offset", + "required": false, + "description": "Offset of timestamp in seconds. Can be positive or negative.", + "schema": { + "type": "integer" + } + }, "query": { "in": "query", "name": "query[]", diff --git a/routes.php b/routes.php index 333057f1..4ce72312 100644 --- a/routes.php +++ b/routes.php @@ -145,6 +145,7 @@ $app->group('/api', function (RouteCollectorProxy $group) { // System $group->get('/system/info', '\Grocy\Controllers\SystemApiController:GetSystemInfo'); + $group->get('/system/time', '\Grocy\Controllers\SystemApiController:GetSystemTime'); $group->get('/system/db-changed-time', '\Grocy\Controllers\SystemApiController:GetDbChangedTime'); $group->get('/system/config', '\Grocy\Controllers\SystemApiController:GetConfig'); $group->post('/system/log-missing-localization', '\Grocy\Controllers\SystemApiController:LogMissingLocalization'); diff --git a/services/ApplicationService.php b/services/ApplicationService.php index 6b4679f3..819572ff 100644 --- a/services/ApplicationService.php +++ b/services/ApplicationService.php @@ -75,4 +75,44 @@ class ApplicationService extends BaseService 'sqlite_version' => $sqliteVersion ]; } + + private static function convertToUtc(int $timestamp): string + { + $dt = new \DateTime('now', new \DateTimeZone('UTC')); + $dt->setTimestamp($timestamp); + return $dt->format('Y-m-d H:i:s'); + } + + private static function getSqliteLocaltime(int $offset): string + { + $pdo = new \PDO('sqlite::memory:'); + if ($offset > 0) + { + return $pdo->query('SELECT datetime(\'now\', \'+' . $offset . ' seconds\', \'localtime\');')->fetch()[0]; + } + else + { + return $pdo->query('SELECT datetime(\'now\', \'' . $offset . ' seconds\', \'localtime\');')->fetch()[0]; + } + } + + /** + * Returns the response for the API call /system/time + * @param int $offset an offset in seconds to be applied + * @return array + */ + public function GetSystemTime(int $offset = 0): array + { + $timestamp = time() + $offset; + $timeLocal = date('Y-m-d H:i:s', $timestamp); + $timeUTC = self::convertToUtc($timestamp); + return [ + 'timezone' => date_default_timezone_get(), + 'time_local' => $timeLocal, + 'time_local_sqlite3' => self::getSqliteLocaltime($offset), + 'time_utc' => $timeUTC, + 'timestamp' => $timestamp, + 'offset' => $offset + ]; + } }