V. 2000 lähestyy, oletko valmis

Arto Juvonen

1. Ongelman tausta

Monissa käytännön tilanteissa ja atk-sovelluksien käyttöliittymissä sekä sovellusten tuottamissa raporteissa vuosiluku on totuttu ilmaisemaan ilman vuosisataa. Tietojen syötössä käyttäjä on säästynyt rutiininomaiselta 19-luvun syötöltä ja raporteissa on säästynyt tulostustilaa. Lisäksi voidaan sanoa, että 19-luvun pois jättäminen on jopa helpottanut lukujen ymmärtämistä, koska lukija on voinut keskittyä oleelliseen informaatioon, siis vuosiluvun kahteen viimeiseen numeroon.

Monet atk-sovellukset on rakennettu niin, että sen lisäksi, että vuosisata on jätetty pois syötöstä ja raporteista, se on (lyhytnäköisesti) jätetty pois myös tiedostoista, tiedon siirrosta muihin järjestelmiin ja ohjelmalogiikasta. Näin on säästytty ylimääräisiltä konversioilta siirrettäessä päivämääriä ohjelman ja syötön välillä tai ohjelman ja raportin välillä. On myös ollut kätevää ja jopa tilaa säästävää tallettaa päivämäärät tiedostoon ilman vuosisataa. Ehkä on haluttu nopeuttaa tiedon siirtoa päivämäärätiedon osalta. 1980-luvulla tehdyissä ohjelmissa ei ole osattu varautua siihen, että ohjelma olisi käytössä 10-20 vuotta. Mielikuvitusta aktivoivia esimerkkejä mahdollisista ongelmakohdista on luetteloitu myös R. Ellerin artikkelissa APL-Uutisissa 1/1998.

2. Vuosi 2000 -ongelma

Vuonna 2000 tapahtuva vuosisadan vaihde tuo mukanaan useita ongelmia, mikäli ohjelmissa vuosiluvuista on käytössä vain kaksi viimeistä numeroa. Näistä tärkeimmät ovat vuosilukujen suuruuden vertailuun, järjestämiseen ja laskentaan liittyvät ongelmat. Vuosisadan vaihteessa päivämäärien suuruuden vertailu tai järjestäminen ei toimi, sillä vertailu 2000 > 1999 ei anna oikeata arvoa luvuilla 00 ja 99. Vastaavasti päivämäärillä laskenta ei toimi. Tyypillinen laskentatehtävä on esim. päivämääräeron laskenta koron laskennassa, 2000-1999 antaa yhden vuoden, mutta 00-99 onkin -99 vuotta. Ongelmia tuottaa myös esim. vuosien lisääminen vuosilukuun. Esim. 98+2 antaa vuoden 100 eikä vuotta 00. Päivämäärälaskenta, esimerkiksi eräpäivän laskenta, on usein hoidettu apufunktiolla. Apufunktio voi kuitenkin olla suunniteltu huomioimaan vain vuosiluvun 2 viimeistä numeroa.

Usein APL:ssä päivämäärätieto käsitellään numerotietona eikä merkkitietona, koska esim. päivämäärävertailut on tällöin helppo toteuttaa. Vuosilukuun on tällöin liitetty esim. kuukausi, kuukausi ja päivä, viikko, viikko ja päivä, juokseva päivä vuoden alusta, vuosineljännes tms. Nämä kaikki lisäävät laskennan monimutkaisuutta. Yleensä vuosi on luvussa merkitsevimmässä paikassa, eli päiväys on vaikka muodossa vvkkpp, koska tämä on mahdollistanut suoraan numeerisen päivämäärän vertailun ja järjestämisen. Jos päivää käsitellään muodossa ppkkvv, on laskentaongelma tullut esiin jo aikaisemminkin ja näin vuosisadan vaihde ei tuone paljon lisäongelmia.

Lukujen muotoiluun liittyy myös ongelmia. Vaikka raportissa haluttaisiinkin vuosi 2000 esittää muodossa '00', muotoilee APL:n perusmuotoilu luvun ilman alkunollia. Tämä on riittänyt tämän vuosisadan päivien muotoilussa.

Oma erikoinen ongelma on suomalaisille sosiaaliturvatunnuksen välimerkin muuttuminen '-':sta 'A':ksi 2000-luvulla syntyvillä henkilöillä. Tunnus on voitu tilan ja laskenta-ajan säästämiseksi tallettaa lukuna, missä on oletettu vain '-':n käyttö tunnuksessa. Jossakin sovelluksessa saatetaan laskea henkilön ikä sosiaaliturvatunnuksen perusteella eikä ehkä ole huomioitu vuosisataa.

3. Ongelman ratkaisu

Ongelman laajuus on tietenkin sovelluskohtainen. Jos sovellus on päivämäärälaskennan osalta pelkkää APL:ää, on tarvittavat konversiot helppo toteuttaa. Jos sovellukseen liittyy päivämäärätietoa sisältäviä tietokantoja, joita mahdollisesti käsitellään muilla, vähemmän joustavilla välineillä, ovat ratkaisutkin sen mukaiset. Seuraavassa keskityn APL-sovelluksiin.

On luultavaa, että vuoden 2000 jälkeenkin halutaan vuosiluvut esittää kahdella tavalla, tietysti nelinumeroisina mutta myös lyhennettynä, eli vain kaksi viimeistä numeroa. Ihmiset tottuvat tulkitsemaan nopeasti esim. päivän 30.9.00 tarkoittamaan 30.9.2000. Eräs luottokorttini on voimassa 04/00 asti. Jos syöttölomakkeessa tai raportissa on tilanpuutetta, on jopa pakko menetellä näin. On myös syytä miettiä, halutaanko koskea vaikkapa raportin muotoiluun, jos siitäkin seuraa ylimääräistä työtä.

Tiedostojen osalta tarvittavat toimenpiteet liittyvät tiedostoratkaisuun. Jos on käytetty APL-tiedostoja, missä esim. päivämäärät ovat omana komponenttinaan numeerisessa muodossa ja tiedosto on keskitetty tietokanta, voidaan ehkä vuosiluvut muuntaa tiedostoon nelinumeroisiksi. Usein tiedostot ovat hajautettuja ja halutaan varmistaa ohjelmiston yhteensopivuus myös vanhojen ei-aktiivisten päivämäärätietojen suhteen. Tällöin tietoja luettaessa tiedot on konvertoitava varmuuden vuoksi, vaikka uudet vuodet olisivatkin nelinumeroisia. Mikäli tiedoston tietueen (merkkimuotoiseen) vuosikenttään on varattu vain kaksi positiota, voi ehkä ainoa keino olla pitää tiedostot vanhassa muodossa.

APL-sovelluksissa päivämäärälaskentaan liittyvä ongelma voidaan ratkaista periaatteessa kahdella tavalla. Jos halutaan pitää vuosiluvut kaksinumeroisina, voidaan käyttää päivämäärälaskentaan funktioita, jotka ottavat vastaan kaksinumeroisia vuosilukuja ja palauttavat tulokset kaksinumeroisina: esim. 98 ADDYEAR 1 2 3 palauttaisi vuosivektorin 99 00 01, vertailussa esim. 99 00 01 GTYEAR 99 palauttaisi 0 1 1. SORTYEAR 99 00 97 palauttaisi 2 3 1. Tätä menettelytapaa voidaan käyttää, jos päivämäärälaskentaa tai päivillä vertailua on vähän tai ongelma on sovelluksessa hyvin lokaali.

Varmaan usein toimivampi ratkaisu saadaan rakentamalla rajapinnat ohjelmasta tiedostoihin, näyttöön ja raportteihin. Näissä rajapinnoissa tapahtuvat tarvittavat vuosilukumuunnokset. Ohjelmassa ja ohjelman käyttämissä muuttujissa vuosilukuja käsitellään aina neljällä numerolla. Päivämäärien käsittelyfunktiot käsittelevät vuosilukuja samoin nelinumeroisina.

Esimerkiksi funktio YMD2YYMD muuntaa päivämäärän, joka on muodossa vvkkpp muotoon vvvvkkpp, siten että vuosista 31-99 tulee 1931-1999 ja vuosista 0-30 tulee 2000-2030.

Mikäli sovelluksessa lasketut vuosiluvut halutaan tallettaa tiedostoon tai näyttää raportissa tai näytöllä kaksinumeroisessa muodossa, käy tämä tietenkin helposti sopivaa jakojäännösfunktiota käyttäen. Esim. 1E6 | vvvvkkpp antaa 6-numeroisen päivämäärän. Muotoiltaessa kaksinumeroisia vuosilukuja raporttiin tai näytölle täytyy huolehtia alkunollien näkymisestä. Esim. päivämäärä 000131 (siis 31.1.2000) tulostuisi väärin yksinkertaista muotoilua käytettäessä. 'Z' parametri ŒFMT-funktiossa on kätevä tässä suhteessa, mikäli kyseinen muotoilufunktio on käytettävissä.

4. Apufunktiot päivämääräkonversioon

Suomen APL-yhdistyksen välityksessä on työtila FADATES, missä on päivämäärien käsittelyyn tarvittavia apufunktioita. Työtila on osajoukko laajemmasta APL-yhdistyksen apufunktiokirjastosta.

Funktio n YRC dates muuntaa päivämäärän vuoden muodosta vv muotoon vvvv. n ilmoittaa päivämäärässä vuosiluvun oikealla puolella olevien numeroiden määrän. Esim. 0 YRC 99 00 01 antaa vuodet muodossa 1999 2000 2001 ja esim. 4 YRC 991231 001231 011231 antaa päivät muodossa 19991231 20001231 20011231.

YRC-funktio muuntaa vuodet seuraavasti:

Lähtövuosi Tulosvuosi
31-99 1931-1999
00-30 2000-2030
100-130 2000-2030 (tämä siltä varalta, että argumentti olisi laskettu vahingossa esim. 99+1)
1900- ei muunnosta

Yllämainitut funktiot olisi määritelty YRC-funktiota käyttäen seuraavasti

ADDYEAR: 100 | (0 YRC ¸)+ ¾

GTYEAR: (0 YRC ¸) > 0 YRC ¾

SORTYEAR: "0 YRC ¾

YMD2YYMD: 4 YRC ¾

Tietysti konversiotarpeet vaihtelevat. Laskutoimituksen jälkeen vuosiluku halutaan joko kaksi- tai nelinumeroisena. Välillä argumentit ovat päivämäärätietoa, välillä muita lukuja. Mikäli APL-tulkki tukee käyttäjän määrittelemiä operaattoreita, voidaan vaihtoehtoisesti käyttää myös muunto-operaattoria.

Operaattori {y} (n YCO f) x muuntaa päivämäärän. Operaattorin argumentti n kertoo, muunnetaanko mahdollinen vasen argumentti y, oikea argumentti x ja tulos. Vastaava n:n alkio on sama, kuin n funktion YRC yhteydessä. Jos n:n alkio on tyhjä vektori (empty), ei muunnosta tehdä.

Yllämainitut funktiot olisi määritelty YCO-operaattoria käyttäen seuraavasti

ADDYEAR: ¸ (0 empty 0 YCO +) ¾

GTYEAR: ¸ (0 0 YCO >) ¾

SORTYEAR: (0 YCO ") ¾

YMD2YYMD: (4 YCO +) ¾

Lienee makuasia, kumpi on elegantimpi tapa, YRC vai YCO. Ohjelmien listaukset ovat jäljempänä.

Huomaa, että FADATES-työtilan apufunktioissa vuosi voi aina olla muodossa vvvv, mutta usein myös muodossa vv, jolloin funktion kommenteissa tästä on maininta. Tehokkuussyistä funktion sisällä ei kuitenkaan tehdä vuosikonversiota, vaan argumenttien tulisi olla oikeassa muodossa.

Tyypillisesti apufunktiot ottavat myöskin vektoriargumentin, jolloin esim. ym. funktiolla voidaan kerralla muuntaa vaikka komponenttitiedoston komponentin kaikki päivämäärät laskennassa tarvittavaan muotoon.

Joissakin tapauksissa on huomattava, että vuosi 2000 on karkausvuosi, mikä onneksi on helpotus joidenkin apufunktioiden ohjelmointiin. Kuten tiedetään, karkausvuodet ovat neljällä jaolliset vuosiluvut. Tästä säännöstä ovat poikkeuksena 100:lla jaolliset vuosiluvut, eivät kuitenkaan 400:lla jaolliset.

 

Funktio YRC

’ Z„POS YRC X;K;R

[1] ©Transform year YY to YYYY in date X of form YYnnnn, where

[2] ©the number of n:s is POS

[3] ©98…1998, 00-30… 2000-2030, 100-130 … 2000-2030

[4] R„30

[5] K„˜0.1+10*POS

[6] Z„X+((1900×K)×X<K×R+101)+(100×K)×X<K×R+1

[7] ©980916 22.00 AJ

Operaattori YCO

’ Z„{Y}(POS YCO F)X;B;K;N;R

[1] ©Operator, that applies function F to dates in X {and Y}

[2] ©Before application transform years from YY to YYYY in X {and Y} of form YYnnnn,

[3] © where the number of n:s is POS[1] (for X), POS[1 2] (for Y and X)

[4] ©If {POS[2/3]} is similar to POS[1], returns the dates in result in 2- number year form

[5] ©POS[i] may be «, which means that that argument/result is not of form date

[6] ©Year conversion: 98…1998, 00-30 … 2000-2030, 100-130 … 2000-2030

[7] B„2=ŒNC'Y' ª R„30

[8] POS„(2+B)†POS,« «

[9] …CO1—¼0¹½N„(ŒIO+B)œPOS

[10] K„˜0.1+10*N

[11] X„X+((1900×K)×X<K×R+101)+(100×K)×X<K×R+1

[12] CO1:…(2=ŒNC'Y')½L1

[13] Z„F X

[14] …END

[15] L1:…CO2—¼0¹½N„ŒIOœPOS

[16] K1„¯1+K„˜0.1+10*N

[17] Y„Y+((1900×K)×Y<K×R+101)+(100×K)×Y<K×R+1

[18] CO2:Z„Y F X

[19] END:…0˜¼0¹½N„(ŒIO+B+1)œPOS

[20] Z„(˜0.1+10*2+†N)|Z

[21] ©980916 21.00 AJ

 

AJ 1998-09-18

e-mail aj@ajoy.com