Latex \today 宏扩展到 1979 年 12 月 31 日

Latex \today macro expanding to December 31st, 1979

通过 nix 包管理器(在 nixos 上)安装 latex,\today 总是扩展到 1979 年 12 月 31 日。我如何得到这个 return 正确的日期?

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 日)。

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

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


更新(感谢@voidee123)

latex uses the environment variable SOURCE_DATE_EPOCH to determine the date.

这导致更简单的解决方案

{
  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}