inweb-bootstrap/docs/foundation-module/3-tm.html
2020-04-09 18:32:37 +01:00

170 lines
16 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Time</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Time' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#3">Chapter 3: The Operating System</a></li><li><b>Time</b></li></ul><p class="purpose">Managing how we record and use the current time and date.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Clock</a></li><li><a href="#SP3">&#167;3. Calendrical</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Clock. </b>From the local environment, we'll extract the time at which we're running.
</p>
<pre class="display">
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">right_now</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">tm</span><span class="plain"> *</span><span class="identifier">the_present</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">fix_time_mode</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Time::begin</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">right_now</span><span class="plain"> = </span><span class="identifier">time</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">the_present</span><span class="plain"> = </span><span class="identifier">localtime</span><span class="plain">(&amp;</span><span class="identifier">right_now</span><span class="plain">);</span>
<span class="identifier">fix_time_mode</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Time::begin is used in 1/fm (<a href="1-fm.html#SP8">&#167;8</a>).</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The command line option <code class="display"><span class="extract">-fixtime</span></code> causes any tool compiled with Foundation
to fix the date as 11 a.m. on 28 March 2016, which is Inform's birthday. This
makes it easier to automate testing, since we can compare output generated
in one session with output generated another, even though that was on two
different dates.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Time::fix</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">tm</span><span class="plain"> </span><span class="identifier">start</span><span class="plain">;</span>
<span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_sec</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_min</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_hour</span><span class="plain"> = </span><span class="constant">11</span><span class="plain">;</span>
<span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_mday</span><span class="plain"> = </span><span class="constant">28</span><span class="plain">; </span><span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_mon</span><span class="plain"> = </span><span class="constant">3</span><span class="plain">; </span><span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_year</span><span class="plain"> = </span><span class="constant">116</span><span class="plain">; </span><span class="identifier">start</span><span class="plain">.</span><span class="identifier">tm_isdst</span><span class="plain"> = -1;</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">pretend_time</span><span class="plain"> = </span><span class="identifier">mktime</span><span class="plain">(&amp;</span><span class="identifier">start</span><span class="plain">);</span>
<span class="identifier">the_present</span><span class="plain"> = </span><span class="identifier">localtime</span><span class="plain">(&amp;</span><span class="identifier">pretend_time</span><span class="plain">);</span>
<span class="identifier">fix_time_mode</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Time::fixed</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">fix_time_mode</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Time::fix is used in 3/cla (<a href="3-cla.html#SP13_1">&#167;13.1</a>).</p>
<p class="endnote">The function Time::fixed appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Calendrical. </b>The date of Easter depends on who and where you are. Inform's notional home
is England. Following League of Nations advice in 1926, Easter is legally
celebrated in England on the Sunday after the second Saturday in April, unless
the Church requests otherwise. Since the Church has made this request every
year since 1926 and shows no sign of coming around, we instead have to turn to
church law, which is where it becomes complicated. There are five main
algorithms ordained by major Christian churches: Catholic, continental
European Protestant, Church of England, Eastern and Russian Orthodox. The
first three always agree on the date, but usually disagree with the last
two. The two eastern algorithms only disagree with each other once or twice
a century, but the usual result has been riots with significant loss of life.
</p>
<p class="inwebparagraph">The official Church of England algorithm is a clumsy one adopted during the
reign of George II. It was then thought important to use a non-Catholic
method of calculation even though the same answer was required. We'll
instead follow the algorithm of J.-M. Oudin, first published in the
Bulletin astronomique in 1940, as adapted by the US Naval Observatory.
Oudin corrected a small mistake in the calculation by Gauss (1800) of the
Allgemeiner Reichskalender (1776) which reconciled Lutheran Easter with
Gregorian, which in turn followed the reforms of Clavius et al. (1582),
which in turn... and so on. See Leofranc Holford-Strevens, "The History of
Time" (Oxford, 2005).
</p>
<p class="inwebparagraph">In principle we calculate the first Sunday after the first ecclesiastical
moon that occurs on or after March 21. An "ecclesiastical moon" is one as
seen from a longitude near Rome, except that the ratios used to adjust lunar and
solar calendars are not quite right. The result is also tampered with to
stop Easter from coinciding with the pagan anniversary of the founding of
Rome (for the convenience of people living in the Vatican) and also to
stop it from coinciding with the Jewish Passover (a change motivated purely
by anti-Semitism). However, since they botched this tampering, it sometimes
does.
</p>
<p class="inwebparagraph">Knuth remarks that calculating Easter was almost the only algorithmic
research in the West for many centuries. Nevertheless the result is
practically a random-number generator. The one thing to be said in its
favour is that it can be computed accurately with integer arithmetic using
fairly low numbers, and this we now do.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CHRISTMAS_FEAST</span><span class="plain"> </span><span class="constant">1</span>
<span class="definitionkeyword">define</span> <span class="constant">EASTER_FEAST</span><span class="plain"> </span><span class="constant">2</span>
<span class="definitionkeyword">define</span> <span class="constant">NON_FEAST</span><span class="plain"> </span><span class="constant">3</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Time::feast</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">this_month</span><span class="plain"> = </span><span class="identifier">the_present</span><span class="plain">-&gt;</span><span class="identifier">tm_mon</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">this_day</span><span class="plain"> = </span><span class="identifier">the_present</span><span class="plain">-&gt;</span><span class="identifier">tm_mday</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">this_year</span><span class="plain"> = </span><span class="identifier">the_present</span><span class="plain">-&gt;</span><span class="identifier">tm_year</span><span class="plain"> + </span><span class="constant">1900</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">, </span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">n</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">l</span><span class="plain">, </span><span class="identifier">m</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">;</span>
<span class="identifier">y</span><span class="plain"> = </span><span class="identifier">this_year</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="identifier">y</span><span class="plain">/100;</span>
<span class="identifier">n</span><span class="plain"> = </span><span class="identifier">y</span><span class="plain">-19*(</span><span class="identifier">y</span><span class="plain">/19);</span>
<span class="identifier">k</span><span class="plain"> = (</span><span class="identifier">c</span><span class="plain">-17)/25;</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">c</span><span class="plain">-</span><span class="identifier">c</span><span class="plain">/4-(</span><span class="identifier">c</span><span class="plain">-</span><span class="identifier">k</span><span class="plain">)/3+19*</span><span class="identifier">n</span><span class="plain">+15;</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-30*(</span><span class="identifier">i</span><span class="plain">/30);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-(</span><span class="identifier">i</span><span class="plain">/28)*(1-(</span><span class="identifier">i</span><span class="plain">/28)*(29/(</span><span class="identifier">i</span><span class="plain">+1))*((21-</span><span class="identifier">n</span><span class="plain">)/11));</span>
<span class="identifier">j</span><span class="plain"> = </span><span class="identifier">y</span><span class="plain">+</span><span class="identifier">y</span><span class="plain">/4+</span><span class="identifier">i</span><span class="plain">+2-</span><span class="identifier">c</span><span class="plain">+</span><span class="identifier">c</span><span class="plain">/4;</span>
<span class="identifier">j</span><span class="plain"> = </span><span class="identifier">j</span><span class="plain">-7*(</span><span class="identifier">j</span><span class="plain">/7);</span>
<span class="identifier">l</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-</span><span class="identifier">j</span><span class="plain">;</span>
<span class="identifier">m</span><span class="plain"> = </span><span class="constant">3</span><span class="plain">+(</span><span class="identifier">l</span><span class="plain">+40)/44;</span>
<span class="identifier">d</span><span class="plain"> = </span><span class="identifier">l</span><span class="plain">+28-31*(</span><span class="identifier">m</span><span class="plain">/4);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">this_month</span><span class="plain"> == </span><span class="identifier">m</span><span class="plain">) &amp;&amp; (</span><span class="identifier">this_day</span><span class="plain"> &gt;= </span><span class="identifier">d</span><span class="plain">-2) &amp;&amp; (</span><span class="identifier">this_day</span><span class="plain"> &lt;= </span><span class="identifier">d</span><span class="plain">+1))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">EASTER_FEAST</span><span class="plain">; </span><span class="comment"> that is, Good Friday to Easter Monday</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">this_year</span><span class="plain"> == </span><span class="constant">2018</span><span class="plain">) &amp;&amp; (</span><span class="identifier">this_month</span><span class="plain"> == </span><span class="constant">3</span><span class="plain">) &amp;&amp; (</span><span class="identifier">this_day</span><span class="plain"> &gt;= </span><span class="constant">30</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">EASTER_FEAST</span><span class="plain">; </span><span class="comment"> Easter Sunday falls on 1 April in 2018</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">this_month</span><span class="plain"> == </span><span class="constant">12</span><span class="plain">) &amp;&amp; (</span><span class="identifier">this_day</span><span class="plain"> &gt;= </span><span class="constant">25</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">CHRISTMAS_FEAST</span><span class="plain">; </span><span class="comment"> that is, Christmas Day to New Year's Eve</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">NON_FEAST</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Time::feast appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="3-drc.html">Back to 'Directories'</a></li><li><i>(This section ends Chapter 3: The Operating System.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>