在(几个)LaTeX 文档中,我需要写一些 Thunderbird 中已有的日期,以便我可以轻松地将它们导出为 ICS(iCalender)文件。复制它们很容易出错,特别是如果任何日期发生变化,很容易忘记更新其中一个文档。所以我正在寻找一个宏,它可以通过引用摘要从 ICS 文件中获取日期。
例如,在文档中我想写:
\documentclass[11pt,a4paper]{article}
\begin{document}
The preliminary talk is on \getdate{preliminary talk}
Homework 0 has its deadline on \getdate{H0 registration}
For further corrections Homework 0 you have until \getdate{H0: correction/H1}
\end{document}
我想将其呈现为:
\documentclass[11pt,a4paper]{article}
\begin{document}
The preliminary talk is on 9.\,3.\,2022
Homework 0 has its deadline on 16.\,3.\,2022
For further corrections Homework 0 you have until 23.\,3.\,2022
\end{document}
如果 CM2022S edit.ics 包含:
BEGIN:VCALENDAR
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Europe/Vienna
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
CREATED:20220215T095816Z
LAST-MODIFIED:20220215T095832Z
DTSTAMP:20220215T095832Z
UID:b33238a0-2a5b-4f02-99ce-1b2bdf71db56
SUMMARY:preliminary talk
DTSTART;TZID=Europe/Vienna:20220309T090000
DTEND;TZID=Europe/Vienna:20220309T100000
TRANSP:OPAQUE
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER;VALUE=DURATION:-PT15M
DESCRIPTION:Mozilla Standardbeschreibung
END:VALARM
END:VEVENT
BEGIN:VEVENT
CREATED:20220215T095835Z
LAST-MODIFIED:20220215T095928Z
DTSTAMP:20220215T095928Z
UID:35c68aee-d920-4904-a57e-39748911f548
SUMMARY:H0 registration
DTSTART;TZID=Europe/Vienna:20220316T235900
DTEND;TZID=Europe/Vienna:20220316T235900
TRANSP:OPAQUE
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER;VALUE=DURATION:-PT15M
DESCRIPTION:Mozilla Standardbeschreibung
END:VALARM
END:VEVENT
BEGIN:VEVENT
CREATED:20220215T095835Z
LAST-MODIFIED:20220215T100118Z
DTSTAMP:20220215T100118Z
UID:f8b373d5-ffd2-49b0-8ad3-7d2bdd7b5eca
SUMMARY:H0: correction/H1
DTSTART;TZID=Europe/Vienna:20220323T235900
DTEND;TZID=Europe/Vienna:20220323T235900
TRANSP:OPAQUE
X-MOZ-GENERATION:2
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER;VALUE=DURATION:-PT15M
DESCRIPTION:Mozilla Standardbeschreibung
END:VALARM
END:VEVENT
END:VCALENDAR
它应该与 pdflatex -no-shell-escape pdfTeX、版本 3.14159265-2.6-1.40.21(TeX Live 2020/Debian)一起使用
答案1
下面是一个不需要的尝试shell-escape
,使用 LaTeX(实际上是 TeX)逐行读取文件(下面的代码主要基于测试从外部文件读取的行)。使用该包检查每一行xstring
是否是 SUMMARY 或 DTSTART 行。该pgfkeys
包用于键值处理(基于有没有办法使用“pgfkeys”设置*全局*键值?)。
请注意,对于 ICS 文件格式的更改,这种方法不是很可靠,例如,字段的顺序必须是摘要位于日期之前(但允许在两者之间插入行)。此外,如果 ICS 文件中有任何反斜杠,该方法将立即失败(而其他特殊字符似乎$
有效)。我强烈建议使用另一种编程语言预处理 ICS 文件,或者检查是否可以将其导出到 csv 并使用 LaTeX 的任何 csv 包。
梅威瑟:
\documentclass[11pt,a4paper]{article}
\usepackage{xstring}
\usepackage{pgfkeys}
\begin{document}
% summary initially empty
\def\currkey{}
\makeatletter
\newread\icsread
\openin\icsread=homework.ics
% don't add end of line character
\begingroup\endlinechar=-1
% read line by line
\@whilesw\unless\ifeof\icsread\fi{%
\read\icsread to \dataline
% check if this is a summary line
\IfBeginWith{\dataline}{SUMMARY}{%
% store summary value in \currkey
\StrBehind{\dataline}{:}[\currkey]%
}{}%
% check if this is a dtstart line
\IfBeginWith{\dataline}{DTSTART}{%
% if a summary has been found previously
\IfStrEq{\currkey}{}{}{%
% extract the full date string
\StrBehind{\dataline}{:}[\currdate]%
% extract year, month, day values
\StrLeft{\currdate}{4}[\curryear]%
\StrMid{\currdate}{5}{6}[\currmonth]%
\StrMid{\currdate}{7}{8}[\currday]%
% generate formatted date
\xdef\fulldate{\currday.\,\currmonth.\,\curryear}%
% store summary value/formatted date as pgfkey
{\globaldefs=1\relax%
\pgfkeyslet{/\currkey}{\fulldate}
}
}}{}%
}%
\endgroup
\closein\icsread
\makeatother
The preliminary talk is on \pgfkeysvalueof{/preliminary talk}
Homework 0 has its deadline on \pgfkeysvalueof{/H0 registration}
For further corrections Homework 0 you have until \pgfkeysvalueof{/H0: correction/H1}
\end{document}
结果:
如果您想在键不存在时生成错误,您可以使用\pgfkeysifdefined
,例如使用以下宏:
\newcommand{\getdate}[1]{%
% if key is defined then print the value
\pgfkeysifdefined{#1}{\pgfkeysvalueof{#1}}{%
% else generate an error
\GenericError{[ICS dates] }{[ICS dates] Key not found}{The key #1 is not defined}{Choose a different key}}%
}