1

通过 nix 包管理器(在 nixos 上)安装了乳胶,\today 总是扩展到 1979 年 12 月 31 日。我如何让它返回正确的日期?

MWE 创建一个目录并添加 mwe.tex 和 flake.nix(基于https://flyx.org/nix-flakes-latex/)。

-- mwe.tex --

\documentclass[11pt]{article}

\title{}
\date{\today}

\begin{document}
\maketitle
\end{document}

-- mwe.tex 到此结束 --

-- flake.nix --

{
  description = "MWE for reproducing \\today macro problem";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        tex = pkgs.texlive.combine {
          inherit (pkgs.texlive) scheme-minimal latex-bin latexmk;
        };
      in rec {
        packages = {
          document = pkgs.stdenvNoCC.mkDerivation rec {
            name = "mwe";
            src = self;
            buildInputs = [ pkgs.coreutils tex ];
            phases = [ "unpackPhase" "buildPhase" "installPhase" ];
            buildPhase = ''
              export PATH="${pkgs.lib.makeBinPath buildInputs}";
              mkdir -p .cache/texmf-var
              env TEXMFHOME=.cache TEXMFVAR=.cache/texmf-var \
                latexmk -pdf -lualatex mwe.tex
            '';
            installPhase = ''
              mkdir -p $out
              cp mwe.pdf $out/
            '';
          };
        };
        defaultPackage = packages.document;
      });
}

-- flake.nix 到此结束 --

然后nix build "."在新目录中运行。结果应该是包含 1979 年 12 月 31 日的 pdf 文件(或者当我刚刚运行它时,我实际上得到了 1980 年 1 月 1 日)。

4

1 回答 1

1

警告:如果您在接近截止日期时发布文档,请使用硬编码日期。

日期很可能基于 UTC,因此如果您的文档是针对本地上下文的,则在一天的开始或结束时提交时,这可能会导致小意外,具体取决于时区。


更新(感谢@voidee123)

latex 使用环境变量 SOURCE_DATE_EPOCH 来确定日期。

这导致了一个更简单的解决方案

{
  description = "MWE for reproducing \\today macro problem";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        tex = pkgs.texlive.combine {
          inherit (pkgs.texlive) scheme-minimal latex-bin latexmk;
        };
      in rec {
        packages = {
          inherit tex;
          document = pkgs.stdenvNoCC.mkDerivation rec {
            name = "mwe";
            src = self;
            nativeBuildInputs = [ pkgs.coreutils pkgs.libfaketime tex ];
            phases = [ "unpackPhase" "buildPhase" "installPhase" ];
            SOURCE_DATE_EPOCH = self.sourceInfo.lastModified;
            buildPhase = ''
              mkdir -p .cache/texmf-var
              env TEXMFHOME=.cache TEXMFVAR=.cache/texmf-var \
                latexmk -pdf -lualatex mwe.tex
            '';
            installPhase = ''
              mkdir -p $out
              cp mwe.pdf $out/
            '';
          };
        };
        defaultPackage = packages.document;
      });
}

上下文的原始答案

Nix 尽最大努力使构建可重现。这包括设置日期,因为太多工具在其输出中留下日期。换句话说,Nix 是一种使构建功能化的工具。在数学函数中,时间将是一个输入或参数。你可以在这里做同样的事情,或者只是硬编码你想要发布文档的日期。

如果它是一个活的文档并且它被提交给 git,你可以使用 flake 元数据(使元数据成为你的“函数”的输入)。您可以在以下期间将其写入构建中的文件buildPhase

# format: YYYYMMDDHHMMSS
echo ${self.sourceInfo.lastModifiedDate} >date.txt
# format: YYYY-MM-DD
echo ${
  nixpkgs.lib.substring 0 4 self.sourceInfo.lastModifiedDate
  + "-" +
  nixpkgs.lib.substring 4 2 self.sourceInfo.lastModifiedDate
  + "-" +
  nixpkgs.lib.substring 6 2 self.sourceInfo.lastModifiedDate
} >date.txt

或者

# format: unix timestamp
echo ${self.sourceInfo.lastModified} >date.txt

然后\input{date.txt},您可以在需要日期的地方使用。

于 2021-12-18T11:51:31.933 回答