Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: QB: Päivämäärillä laskeminen

jsbasic [22.12.2003 11:29:11]

#

DATE$ta ja muista saatavan "MM-DD-YYYY" luvun muutto päiviksi ja toisinpäin, ja pari esimerkkiä.

Helppo käyttää, jos muistaa qb:n VAL ja STR$ funktiot. Veikkaan että joku tarttee tätä.

DECLARE FUNCTION dateVAL (pvm$)
DECLARE FUNCTION dateSTR$ (paivat)
DECLARE FUNCTION viikonpaiva (paivat)
DECLARE FUNCTION karkausvuosi (vuosi)

'PÄIVÄMÄÄRIEN LASKEMINEN JSBasic 2003
'
'DateVAL muuttaa päivämäärämerkkijonon (MM-DD-YYYY) päiviksi
'0-vuodesta lähtien ja DateSTR$ toisinpäin. Päivillä on helppo
'laskea erilaisia juttuja:

'Otetaan vaikka aika vuosituhannenvaihteesta:
millenium2000 = dateVAL("01-01-2000")

'Sitten aika seuraavasta vuosituhannenvaihteesta:
millenium3000 = dateVAL("01-01-3000")

'Otetaan paivat koneen kellosta eli DATE$sta:
tanaan = dateVAL(DATE$)

'Lasketaanpa:
CLS
PRINT "- Tässä vuosituhannessa on"; millenium3000 - millenium2000; "paivaa."
PRINT "- Vuosituhannen vaihteesta on nyt kulunut"; tanaan - millenium2000; "päivää,"
PRINT "  eli"; (tanaan - millenium) / 30; "kuukautta,"
PRINT "  eli"; (tanaan - millenium) / 365; "vuotta."
PRINT "-"; (tanaan - millenium2000) / (millenium3000 - millenium2000) * 100; "% vuosituhannesta on käytetty."
PRINT "- Seuraavaan on aikaa enää:"; (millenium3000 - tanaan) / 365; "vuotta."
PRINT
PRINT "- Tänään on"; viikonpaiva(tanaan); "päivä viikosta."
PRINT "- Tasan 10000 päivää sitten oli "; dateSTR$(tanaan - 10000); "."
PRINT "- Silloin oli"; viikonpaiva(tanaan - 5000); "päivä viikosta."

FUNCTION dateSTR$ (paivat)
  'Muuttaa päivät vuodesta 0 asti merkkijono-päivämääräksi (MM-DD-YYYY)

  jaljella = INT(paivat)
  IF jaljella > 723500 THEN jaljella = jaljella - 723180: vuosi = 1980

  DIM kk AS INTEGER

  WHILE jaljella > 366
    vuosi = vuosi + 1
    jaljella = jaljella - 365 - karkausvuosi(vuosi)
  WEND

  DIM kkpit(12)
  kkpit(1) = 31
  IF karkausvuosi(vuosi) = 1 THEN kkpit(2) = 29 ELSE kkpit(2) = 28
  kkpit(3) = 31
  kkpit(4) = 30
  kkpit(5) = 31
  kkpit(6) = 30
  kkpit(7) = 31
  kkpit(8) = 31
  kkpit(9) = 30
  kkpit(10) = 31
  kkpit(11) = 30
  kkpit(12) = 31

  WHILE jaljella > 31
    kk = kk + 1
    jaljella = jaljella - kkpit(kk)
  WEND

  kk = kk + 1
  paiva = jaljella - 1 + karkausvuosi(vuosi)

  IF kk < 10 THEN tqbpvm$ = tqbpvm$ + "0"
  tqbpvm$ = tqbpvm$ + LTRIM$(RTRIM$(STR$(kk))) + "-"
  IF paiva < 10 THEN tqbpvm$ = tqbpvm$ + "0"
  tqbpvm$ = tqbpvm$ + LTRIM$(RTRIM$(STR$(paiva))) + "-"
  tqbpvm$ = tqbpvm$ + LTRIM$(RTRIM$(STR$(vuosi)))

  dateSTR$ = tqbpvm$
END FUNCTION

FUNCTION dateVAL (pvm$)
  'Muuttaa merkkijono-päivämäärän (MM-DD-YYYY) päiviksi vuodesta 0 alkaen.

  kk = VAL(MID$(pvm$, 1, 2))
  paiva = VAL(MID$(pvm$, 4, 2))
  vuosi = VAL(MID$(pvm$, 7, 4))

  FOR lvuosi = 0 TO vuosi - 1
    luku = luku + 365
    IF karkausvuosi(lvuosi) THEN luku = luku + 1
  NEXT

  DIM kkpit(12)
  kkpit(1) = 31
  IF karkausvuosi(vuosi) THEN kkpit(2) = 29 ELSE kkpit(2) = 28
  kkpit(3) = 31
  kkpit(4) = 30
  kkpit(5) = 31
  kkpit(6) = 30
  kkpit(7) = 31
  kkpit(8) = 31
  kkpit(9) = 30
  kkpit(10) = 31
  kkpit(11) = 30
  kkpit(12) = 31
  FOR lkk = 1 TO kk - 1
    luku = luku + kkpit(lkk)
  NEXT

  luku = luku + paiva
  dateVAL = luku
END FUNCTION

FUNCTION karkausvuosi (vuosi)
  'Laskee onko annettu vuosi karkausvuosi (1)
  IF vuosi MOD 100 THEN
    IF (vuosi MOD 4) = 0 THEN karkausvuosi = 1
  ELSE
    IF (vuosi MOD 400) = 0 THEN karkausvuosi = 1
  END IF
END FUNCTION

FUNCTION viikonpaiva (paivat)
  'Laskee viikonpaivan annetusta paivasta vuodesta 0 asti
  viikonpaiva = (paivat + 4) MOD 7 + 1
END FUNCTION

sooda [22.12.2003 21:24:20]

#

Ihan kiva. Ja tohon karkausvuosiin on lyhyempikin tapa: karkaako = (vuosi MOD 4 == 0 and vuosi MOD 100 <> 0) or (vuosi MOD 400 == 0)

PaavoOR [11.03.2005 22:18:00]

#

Toimiiko tämä todella. Itselläni ei ole QBasic kääntäjää, että pystyisin testaamaan. Tietääkseni on mahdotonta laskea tietokoneella päivien lukumäärä vuodesta nolla, koska ajanlasku on muuttunut vuonna 1584 (tai joskus niihin aikoihin). Mm. karkausvuosien laskutapa on muuttunut tuolloin. Muistaakseni silloin myös harpattiin jostain päivämäärästä toiseen. Mutta esim. 1600 luvulta on mahdollista laskea tietokoneella aika nykyhetkeen. Jos jotakin kiinnostaa, niin olenkin tehnyt siitä ikuisen kalenterin, joka löytyy osoitteesta www.tarppi.net . Sivut ovat muuten vielä keskeneräiset.

Grez [16.10.2019 14:04:19]

#

Vanhan koodivinkin noston kommentti (tm)

Ihmettelen vinkissä, miksi kuukausien pituudet on määritelty koodissa kahteen kertaan.

PaavoOR kirjoitti:

Toimiiko tämä todella. Itselläni ei ole QBasic kääntäjää, että pystyisin testaamaan. Tietääkseni on mahdotonta laskea tietokoneella päivien lukumäärä vuodesta nolla, koska ajanlasku on muuttunut vuonna 1584 (tai joskus niihin aikoihin). Mm. karkausvuosien laskutapa on muuttunut tuolloin.

En näe miten tietokoneella olisi mahdotonta laskea päivien lukumäärää, jos vaan tapahtuneet muutokset on tiedossa ja ne kerrotaan tietokoneelle. Tietenkin jos päivien määrää on ylipäätään mahdoton laskea millään keinoin (eli ei tiedetä miten ne on menneet) niin silloinhan se ei luonnollisesti onnistu tietokoneellakaan.

Toisaalta eipä sillä misäsän käytännön asiassa varmasti ole merkitystä, laskeeko joku ohjelma päivien määrät vuosisatojen taakse oikein.

Matti Holopainen [17.10.2019 15:21:38]

#

Tulipa mieleen, että olen tehnyt 1970-luvun alussa HP 2000 Basic osituskäyttöjärjestelmään vastaavat funktiot. Muistia oli vähän, jonka vuoksi piti toimia ilman taulukoita. Esittelen tässä nämä funktiot C-kielellä toteutettuina, nyt versiona, jossa ajan nollapiste on 1.1.1986.

/* Muuntaa päivämäärän päiviksi vuoden 1986 alusta */
int date_days1986(int y, int m, int d)
{
  /* Lisää kuluvan vuoden aikaisempien kuukausien päivät */
  d += (m * 30.575 - 30.075);

  /* Lisää edellisten vuosien päivät */
  d += (y * 365.25 - 725386.24);

  /* Helmikuun ja karkausvuoden vaikutus. */
  return d - (m <= 2) ? 1 : (y & 3) ? 3 : 2;
}

/* Muuntaa päivät vuoden 1986 alusta päivämääräksi */
void days1986_date(int days, int* y, int* m, int* d)
{
  /* Vuoden arvaus yläkanttiin ja hienosäätö */
  for (*y = 1986 + days/365 + 1; (*d = days - date_days1986(*y,1,1)) < 0; (*y)--);

  /* Kuukauden arvaus yläkanttiin ja hienosäätö */
  for (*m = *d > 330 ? 12 : (*d+31)/30; (*d = days - date_days1986(*y,*m,1)) < 0; (*m)--);

  (*d)++;
}

Molemmat funktiot on testattu kaikilla vuosien 1986 ja 2099 välisillä päivämäärillä. Joulukuu 2099 ei yksinkertaisen karkausvuosisäännön (y & 3) vuoksi toimi oikein.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta