diff --git a/nixos/modules/config/timezone.nix b/nixos/modules/config/timezone.nix index 39a45042c6cc..9f849c24c113 100644 --- a/nixos/modules/config/timezone.nix +++ b/nixos/modules/config/timezone.nix @@ -14,13 +14,16 @@ in time = { timeZone = mkOption { - default = "UTC"; - type = types.str; + default = null; + type = types.nullOr types.str; example = "America/New_York"; description = '' The time zone used when displaying times and dates. See for a comprehensive list of possible values for this setting. + + If null, the timezone will default to UTC and can be set imperatively + using timedatectl. ''; }; @@ -40,13 +43,14 @@ in # This way services are restarted when tzdata changes. systemd.globalEnvironment.TZDIR = tzdir; - environment.etc.localtime = - { source = "/etc/zoneinfo/${config.time.timeZone}"; - mode = "direct-symlink"; + systemd.services.systemd-timedated.environment = lib.optionalAttrs (config.time.timeZone != null) { NIXOS_STATIC_TIMEZONE = "1"; }; + + environment.etc = { + zoneinfo.source = tzdir; + } // lib.optionalAttrs (config.time.timeZone == null) { + localtime.source = "/etc/zoneinfo/${config.time.timeZone}"; + localtime.mode = "direct-symlink"; }; - - environment.etc.zoneinfo.source = tzdir; - }; } diff --git a/nixos/tests/timezone.nix b/nixos/tests/timezone.nix new file mode 100644 index 000000000000..2204649a3fc4 --- /dev/null +++ b/nixos/tests/timezone.nix @@ -0,0 +1,45 @@ +{ + timezone-static = import ./make-test.nix ({ pkgs, ... }: { + name = "timezone-static"; + meta.maintainers = with pkgs.lib.maintainers; [ lheckemann ]; + + machine.time.timeZone = "Europe/Amsterdam"; + + testScript = '' + $machine->waitForUnit("dbus.socket"); + $machine->fail("timedatectl set-timezone Asia/Tokyo"); + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); + $dateResult[1] eq "1970-01-01 01:00:00\n" or die "Timezone seems to be wrong"; + ''; + }); + + timezone-imperative = import ./make-test.nix ({ pkgs, ... }: { + name = "timezone-imperative"; + meta.maintainers = with pkgs.lib.maintainers; [ lheckemann ]; + + machine.time.timeZone = null; + + testScript = '' + $machine->waitForUnit("dbus.socket"); + + # Should default to UTC + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); + print $dateResult[1]; + $dateResult[1] eq "1970-01-01 00:00:00\n" or die "Timezone seems to be wrong"; + + $machine->succeed("timedatectl set-timezone Asia/Tokyo"); + + # Adjustment should be taken into account + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); + print $dateResult[1]; + $dateResult[1] eq "1970-01-01 09:00:00\n" or die "Timezone was not adjusted"; + + # Adjustment should persist across a reboot + $machine->shutdown; + $machine->waitForUnit("dbus.socket"); + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); + print $dateResult[1]; + $dateResult[1] eq "1970-01-01 09:00:00\n" or die "Timezone adjustment was not persisted"; + ''; + }); +}