Sharp Pocket Computer - Handling the Date

## Handling the Date with your Sharp Pocket Computer

### Helper functions

One function we might need is the `modulo` function. This is the rest of an integer division, e.g. the result of `5 MOD 3` is `2`. The BASIC representation of `Y = A MOD B` is

```10 Y=A-B*INT(A/B)
```

### Storing the Date in BASIC variables

The easiest way to do this is to use three standard variables, like `Y` for year, `M` for month and `D` for day. The advantages of this are
• Easy to understand
• The date may be printed with e.g. `10 PRINT "Date is";D;M;STR\$ Y`
• Takes three variables for only one date
• It is hard to create a sequence of dates
• It is also hard to determine the weekday or the difference of days between two dates
Another way to store the date is to use a single variable and store the date as difference in days to a fixed date, e.g. to the 15.Oct.1582 (which is the start of the gregorian calendar). The advantages of this are
• Takes only one variable to represent one date
• It is easy to create a sequence of dates
• It is also easy to determine the weekday or the difference of days between two dates
• Hard to understand
• Hard to print

#### Which one would be the best reference date?

A good reference date would be the 15.Oct.1582 (start of the gregorian calendar), the difference is always positive for all valid gregorian calendar dates then and the values are simpler to understand then. As you will see, it is easier to calculate with the 1. March 0000 as reference day. Note that this is only a virtual difference of days, because the gregorian calendar was not valid this time (and the first year was one, not zero).

Because both representation format have their advantages, it would be nice to convert them one to another. This leads us directly to the

### Conversion Subroutines for Date formats

#### Converting D,M,Y to a Difference of Days to a fixed Date

The fixed date will be the 1. March 0000 in all further calculations. First let's convert the month (Jan.- Dec. or 1- 12) as shown in the following table:

 Month converted Offset in days to 1. March January (1) 10 306 February (2) 11 337 March (3) 0 0 April (4) 1 31 May (5) 2 61 June (6) 3 92 July (7) 4 122 August (8) 5 153 September (9) 6 184 October (10) 7 214 November (11) 8 245 December (12) 9 275

The calculation to to this is `MC = (M + 9) MOD 12`. `MC` stands for "Month converted" here.

In BASIC this is

```10 MC=M+9-12*INT((M+9)/12)
```

Why? Because we will not have to respect februarys with 29 days. The month offset in days to the 1. March (you can see it in the third column of the table) is the same for years with 365 days and years with 366 days.

Now, we're able to calculate the difference in days to the 1. March in a single year. It is the month offset from the table plus the day part of the date minus one. How is it possible to represent the month offset table in the sharp? The simplest approach would be to create an array and fill it with the offset at program start. This is very memory-consuming, but fortunately I found a function, which is able to calculate this:

``` INT(MC*30,6+0,5) ```

Let's have a look at the year now: If the month is January or February, we have to reduce the number of years by one year, because these two month belong to the past year due to the month conversion calculation. In BASIC this would be (`YC` stands for "Year corrected")

```10 YC=Y:IF M<3 LET YC=YC-1
```

Without years with 366 days it would be simple: The offset in days would be `diff = YC * 365`.

With respecting the years with 366 days it is `diff = INT(YC * 365,25)`.

But there are some extra rules for years with 366 days:

• If the year is (integer-) dividable (without rest) by 100, the year has 365 days, except
• if the year is dividable by 400, the year has 366 days.

The function, which respects this, looks like this (in BASIC):

```10 DI= INT (YC*365.25)- INT (YC/100)+ INT (YC/400)
```

Now, let's respect the days: The difference of days to the first day of the month is simply the number minus one.

Here is a complete subroutine, which calculates the difference in days to the 1. March 0000:

```10 rem  CONVERT DATE IN D,M,Y TO NUMBER OF DAYS
20 rem  SINCE 1.MARCH 0000; RESULT IS IN A
30 A=Y:if M<3 let A=A-1
40 A=int (A*365.25)-int (A/100)+int (A/400)+D-1
50 A=A+int (.5+30.6*(M+9-12*int ((M+9)/12))):return```

Note, that this is very efficient, it is straight forward, there are no loops and there is no array for determining the number of days for a month.

#### Converting the Difference of Days (to the 1. March 0000) to Day, Month and Year

First, let's have a look at the year: Calculating the year is rather complicated, because the INT operation is not reversible. But `Y = diff / 365,2425` will give a value that will match in most cases. If you add two to the difference (`Y = (diff + 2) / 365,2425`), the result will

• match in most cases
• if it doesn't match, the result will be greater than the real year (this is easier to handle, because you must not respect years with 366 days)
After we've calculated this value, we have to
• Calculate the real number of days this number of years causes
• Decrease the number of years, if it causes more days than the given value
In BASIC this would be:

```10 Y=INT((DI+2)/365.2425)
20 D=INT(Y*365.25)-INT(Y/100)+INT(Y/400):IF D>DI LET Y=Y-1:GOTO 10
30 DI=DI-D
```

Note, that we have to add one to the year, if the month is less than 3 (March), but to do this, we'll first calculate the month. This is most similar to calculating the number of years. Just calculate a nearby-value, an then correct it. In BASIC this would be

```40 M=INT(DI/30)
50 D=INT(.5+30.6*M):IF D>DI LET M=M-1:GOTO 40
60 DI=DI-D
```

You must correct the month with

```70 M=M+3-12*INT((M+2)/12)
```

And correct the year.

```80 IF M<3 LET Y=Y+1
```

The day is the remaining difference plus one:

```90 D=DI+1
```

Here's a full code example:

```10 rem  CONVERT NUMBER OF DAYS SINCE 1.MARCH 0000
20 rem  (STD.VAR. A) TO D,M,Y; CONTENT OF VAR. A IS DESTROYED
30 Y=INT((A+2)/365.2425)
40 D=INT(Y*365.25)-INT(Y/100)+INT(Y/400):IF D>A LET Y=Y-1:GOTO 40
50 A=A-D:M=INT(A/30)
60 D=INT(.5+30.6*M):IF D>A LET M=M-1:GOTO 60
70 D=A-D+1:M=M+3-12*INT((M+2)/12):IF M<3 LET Y=Y+1
80 RETURN
```

#### Getting the Day of Week for a given Date

For doing this, you need the date as number of days since 1.March 0000. Then you calculate `(diff + 2) modulo 7`. In BASIC this is

```10 WD=A+2-7*INT((A+2)/7)
```

The monday is 0, the duesday is 1 and so on. Edgar Pühringer last modified: 2009-10-14 