Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/DeprecatedString.h>
8#include <LibCore/ArgsParser.h>
9#include <LibCore/DateTime.h>
10#include <LibCore/System.h>
11#include <LibMain/Main.h>
12#include <time.h>
13
14ErrorOr<int> serenity_main(Main::Arguments arguments)
15{
16 TRY(Core::System::pledge("stdio settime rpath"));
17
18 bool print_unix_date = false;
19 bool print_iso_8601 = false;
20 bool print_rfc_3339 = false;
21 bool print_rfc_5322 = false;
22 StringView set_date;
23 StringView format_string;
24
25 Core::ArgsParser args_parser;
26 args_parser.add_option(set_date, "Set system date and time", "set", 's', "date");
27 args_parser.add_option(print_unix_date, "Print date as Unix timestamp", "unix", 'u');
28 args_parser.add_option(print_iso_8601, "Print date in ISO 8601 format", "iso-8601", 'i');
29 args_parser.add_option(print_rfc_3339, "Print date in RFC 3339 format", "rfc-3339", 'r');
30 args_parser.add_option(print_rfc_5322, "Print date in RFC 5322 format", "rfc-5322", 'R');
31 args_parser.add_positional_argument(format_string, "Custom format to print the date in", "format-string", Core::ArgsParser::Required::No);
32 args_parser.parse(arguments);
33
34 if (!set_date.is_empty()) {
35 auto number = set_date.to_uint();
36
37 if (!number.has_value()) {
38 warnln("date: Invalid timestamp value");
39 return 1;
40 }
41
42 timespec ts = { number.value(), 0 };
43 TRY(Core::System::clock_settime(CLOCK_REALTIME, &ts));
44
45 return 0;
46 }
47
48 if (print_unix_date + print_iso_8601 + print_rfc_3339 + print_rfc_5322 + !format_string.is_null() > 1) {
49 warnln("date: Multiple output formats specified");
50 return 1;
51 }
52
53 auto date = Core::DateTime::now();
54 if (!format_string.is_null()) {
55 // FIXME: If the string argument does not start with a '+' sign, POSIX says
56 // we should parse that as a date, and set the system time to it.
57 if (format_string.length() == 0 || format_string[0] != '+') {
58 warnln("date: Format string must start with '+'");
59 return 1;
60 }
61 outln("{}", date.to_deprecated_string(format_string.substring_view(1)));
62 } else if (print_unix_date) {
63 outln("{}", date.timestamp());
64 } else if (print_iso_8601) {
65 outln("{}", date.to_deprecated_string("%Y-%m-%dT%H:%M:%S%:z"sv));
66 } else if (print_rfc_5322) {
67 outln("{}", date.to_deprecated_string("%a, %d %b %Y %H:%M:%S %z"sv));
68 } else if (print_rfc_3339) {
69 outln("{}", date.to_deprecated_string("%Y-%m-%d %H:%M:%S%:z"sv));
70 } else {
71 outln("{}", date.to_deprecated_string("%Y-%m-%d %H:%M:%S %Z"sv));
72 }
73 return 0;
74}