Kirjoittaja Aihe: [ ratkaistu ] python syöterivin tarkistaminen  (Luettu 4237 kertaa)

teele

  • Käyttäjä
  • Viestejä: 809
    • Profiili
[ ratkaistu ] python syöterivin tarkistaminen
« : 12.01.21 - klo:15.26 »
Kokeilussa olisi seuraavanlainen syöterivi

nimi   aika   kilomäärä   laji   täsmennys

Tietotyypit olisi suunniteltu tällaisiksi pythonissa

string  int   float    string   string

Ja sitten haluttaisiin tarkistaa, että syötettävät arvot ovat ensiksi kieliopillisesti oikein ja sitten, jos  kaikki onnistuu, että annetut arvot ovat muuten sopivia.

Yksi tapa olisi varmaan pythonin regex, mutta tällainen kysymys on varmaan ratkaistu jo aikaisemmin monta kertaa muillakin tavoilla eikä nyt edes ole ideana alkää kirjoittaa kaikkea ihan reqexistä lähtien.

Löytyisikö asiaan valmisratkaisuja. Netistä en ole ainakaan vielä näppärää ratkaisua löytänyt.


« Viimeksi muokattu: 23.01.21 - klo:18.33 kirjoittanut teele »

SuperOscar

  • Käyttäjä
  • Viestejä: 3993
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: python syöterivin tarkistaminen
« Vastaus #1 : 12.01.21 - klo:19.24 »
Tuo ei oikein riitä luonnehdinnaksi: pitäisi tietää, mitä merkkejä kukin merkkijono voi sisältää ja miten kentät erotetaan.

Mutta olettaen että erottimena on sanaväli eikä sitä käytetä merkkijonoissa, tuossa pärjäisi str.split()-metodilla. Esimerkiksi jos ”rivi” sisältää rivillisen tekstiä:

Koodia: [Valitse]
nimi, aika, kilot, laji, tasmennys = rivi.strip().split()
try:
    aika = int(aika)
    kilot = float(kilot)
except ValueError:
    print("Virhe! Virhe!")

Tuossa antaisit siis Pythonin itsensä tarkistaa lukujen oikeellisuuden yrittämällä vain ronskisti muuttaa merkkijonon luvuksi.

Jos syötteessä liukuluvussa desimaalierottimena on pisteen sijaan pilkku, täytyy aavistuksen viilata:

Koodia: [Valitse]
    kilot = float(kilot.replace(',', '.'))
Jos muuten syöte on CSV-tiedosto, kannattaa saman tien käyttää csv-moduulia. Sen avulla lainausmerkkien ym. hallinta sujuu helpoimmin.
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

teele

  • Käyttäjä
  • Viestejä: 809
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #2 : 12.01.21 - klo:20.37 »

Juuri noilla neuvoilla käpistely etenee

Koodia: [Valitse]
rivi1 = 'päre 20210112 10.123 tarvike kattopäreet'
rivi2 = rivi1.strip().split()
print(rivi2)

try:
    aika = int(rivi2[1])
    kilot = float(rivi2[2])
except ValueError:
    print("Virhe! Virhe!")

print(kilot)
print(aika)

En vielä laita säiettä ratkaistuksi, tässä voi tulla vielä muita ongelmia ....  :)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: python syöterivin tarkistaminen
« Vastaus #3 : 14.01.21 - klo:11.06 »
Puhutun kielen kieliopillisesti vähän haastavampi toteuttaa tietokonekielellä, joskaan ei mahdoton. Tarkoitit varmaan Python-kielellä kieliopillisesti oikein?

Tässä aamu vierähtänyt humaanimman keskustelun tiimellyksessä Uusi Suomi -blogissa, niin tuli yhdistettyä tuo kielioppi nimenomaan luonnolliseen kieleen ensiksi, anteeksi tämä huomautus.

Mitä Pythonin versiota käytät? Tuli mieleen tuosta ajasta, että mitä UNIX-järjestelmässäkin lasketaan aika long-tyyppisestä muuttujasta, mutta Python 3 -versiossa ei ole enää longia. Kakkosessa on vielä. Mutta aikaan ehkä kannattaisi hyödyntää datetime -moduulia kokonaisluvun sijaan, jos ajatellaan jotain tietokantaan vientiä arkistointia varten tiedon varastointia yms.

Yksinkertainen esimerkki, miten Pythonissa saa käyttöön ajan ohjelmoinnin.
Koodia: [Valitse]
import datetime

x = datetime.datetime.now()
print(x)
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

SuperOscar

  • Käyttäjä
  • Viestejä: 3993
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: python syöterivin tarkistaminen
« Vastaus #4 : 14.01.21 - klo:11.44 »
Mitä Pythonin versiota käytät? Tuli mieleen tuosta ajasta, että mitä UNIX-järjestelmässäkin lasketaan aika long-tyyppisestä muuttujasta, mutta Python 3 -versiossa ei ole enää longia.

Kenenkään ei pitäisi enää käyttää Python 2:ta, koska sen tuki on päättynyt.
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: python syöterivin tarkistaminen
« Vastaus #5 : 14.01.21 - klo:15.03 »
Mitä Pythonin versiota käytät? Tuli mieleen tuosta ajasta, että mitä UNIX-järjestelmässäkin lasketaan aika long-tyyppisestä muuttujasta, mutta Python 3 -versiossa ei ole enää longia.

Kenenkään ei pitäisi enää käyttää Python 2:ta, koska sen tuki on päättynyt.

Eipä sitä taida enää ketään käyttääkään, ainakaan uusien sovellusten ohjelmointiin. En tiedä sitten, onko teollisuuskäytössä jotkin ohjelmistokehittäjät ylläpitävät vielä Python 3:a edeltävillä versioilla ohjelmoituja ohjelmakoodeja. Voi olla, että ei.

Itsellänikin on Ubuntu-kannettavassani Python 2 asennettuna, mutta ohjelmoin Python 3:lla sen, mitä ohjelmoin Pythonilla sillä ajan kuluksi välillä kun katson jotain uutta.
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: python syöterivin tarkistaminen
« Vastaus #6 : 14.01.21 - klo:15.15 »
Tuosta tuli vielä mieleen, kun mainitsin, että UNIX-järjestelmässä lasketaan long-tyyppisestä muuttujasta aika, mutta asia ei ole niin yksinkertainen näköjään.

https://en.wikipedia.org/wiki/Unix_time

UNIX-aika ja myös siis Linux ja Ubuntussa ajan määrittely, Date -ohjelma ikäänkuin.

Aloin kaivamaan netistä ohjeita, miten tuosta long-tyyppisestä millisekuntti-arvosta saa laskettua, laskukaavaa tai jotain, jonkin ihmisen ymmärrettävään muotoon muinaisten sumerilaisten 12/60 -järjestelmään perustuvan ajankohdan. Voisi olla ihan mielekäs harjoitus ohjelmoinnin osalta, jos tulee tilanne, että ei millään keksi mitään tekemistä paremman puutteessa.

Ei tosin tuosta ajanlaskenta -metodista mitään käytännön hyötyä ole, kun tosiaan yksi sekunti on 1000 millisekuntia, niin siitähän ajan saa, ja kaikissa ohjelmointikielissä varmaan jo implementoitu valmiina jokin päivämäärä/aika -funktio tai -kirjasto, että ei tarvitse lähteä tyhjästä laskemaan.

Mutta kai aikaa voi käyttää pyörän keksimiseen norsunluutasolla, kuka käyttää aikansa mihinkin paremman tekemisen puutteessa?

Unixin ajan alkuarvo 01.01.1970 on nolla, ja siitä sitten varmaan millisekunteina laskettuna siitä eteenpäin loput ajat, ketä tuon Date, tai nuo muut aika-sovellukset ohjelmoinut alunperin Unixin kehittäjät.
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: python syöterivin tarkistaminen
« Vastaus #7 : 14.01.21 - klo:15.33 »
Java-koodia
Koodia: [Valitse]
import java.util.Date;
public class Aika {

public static void main(String[] args) {

//Muuttujien määrittely
long aika = System.currentTimeMillis();
long muutettu = aika/1000/60/24;
long tulevaisuus = Long.MAX_VALUE;

//Luodaan Date -tietotyypin ilmentymät, oliot.
Date now = new Date(aika);
Date history = new Date(muutettu);
Date endOfWorld = new Date(tulevaisuus);

//Tulostetaan testitulokset
System.out.println(now);
System.out.println(history);
System.out.println(endOfWorld);

//Onkohan ihminen vielä 292278994 -vuonna elossa ja UNIX-pyörimässä palvelimella?
}
}

Tuloste:
Koodia: [Valitse]
Thu Jan 14 15:35:47 EET 2021
Thu Jan 01 02:18:38 EET 1970
Sun Aug 17 09:12:55 EET 292278994

Tuon jakolaskun tuossa koodissa pitäisi antaa aika lähelle 1970-vuoden tammikuun alkua olevan ajan, eli lähelle nollaan jaon tuloksena antaa tuon long -muuttujan, mutta tuossa varmaan vähän reilun kahden tunnin heitto kun Suomessa on Greenwich MeanTime +2 -aikavyöhyke käytössä, niin jos tuon 2 tuntia vähentää, niin aika lähelle 00:00:00 pääseen 01.01.1970.

Tuolla Unix-Time -Wikipedian artikkelista selvisi, kun luin sen nyt ensimmäistä kertaa, että UNIX-ajanlaskun perustuu UTC -alkukantaiseen aikavyöhykestandardiin, joka on vaikutteena toiminut tuolle GMT:lle.

Suora lainaus Wikipediasta:

Koodia: [Valitse]
"Coordinated Universal Time It is effectively a successor to Greenwich Mean Time (GMT).".

Tuolla artikkelissa mainitaan myös, että UNIXin ajan alkuarvo ei ole aito esitys tuosta UTC-standardin nolla-arvosta.


« Viimeksi muokattu: 14.01.21 - klo:15.39 kirjoittanut Jere Sumell »
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

JaniAlander

  • Käyttäjä / moderaattori+
  • Viestejä: 3319
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #8 : 14.01.21 - klo:17.57 »
Tuosta tuli vielä mieleen, kun mainitsin, että UNIX-järjestelmässä lasketaan long-tyyppisestä muuttujasta aika, mutta asia ei ole niin yksinkertainen näköjään.

https://en.wikipedia.org/wiki/Unix_time

UNIX-aika ja myös siis Linux ja Ubuntussa ajan määrittely, Date -ohjelma ikäänkuin.

Aloin kaivamaan netistä ohjeita, miten tuosta long-tyyppisestä millisekuntti-arvosta saa laskettua, laskukaavaa tai jotain, jonkin ihmisen ymmärrettävään muotoon muinaisten sumerilaisten 12/60 -järjestelmään perustuvan ajankohdan. Voisi olla ihan mielekäs harjoitus ohjelmoinnin osalta, jos tulee tilanne, että ei millään keksi mitään tekemistä paremman puutteessa.

Ei tosin tuosta ajanlaskenta -metodista mitään käytännön hyötyä ole, kun tosiaan yksi sekunti on 1000 millisekuntia, niin siitähän ajan saa, ja kaikissa ohjelmointikielissä varmaan jo implementoitu valmiina jokin päivämäärä/aika -funktio tai -kirjasto, että ei tarvitse lähteä tyhjästä laskemaan.

Mutta kai aikaa voi käyttää pyörän keksimiseen norsunluutasolla, kuka käyttää aikansa mihinkin paremman tekemisen puutteessa?

Unixin ajan alkuarvo 01.01.1970 on nolla, ja siitä sitten varmaan millisekunteina laskettuna siitä eteenpäin loput ajat, ketä tuon Date, tai nuo muut aika-sovellukset ohjelmoinut alunperin Unixin kehittäjät.

Heeh tuli toissa syksynä painittua pythonin, unix-ajan ja perinteisen ajan kanssa. En nyt muista heti kättelyssä minkä ratkaisun kehitin, sen muistan että erillistä valmista moduulia käyteltiin ja sai sitten merkkijonojakin manipuloida urakalla :D
Core i5-9400F 2.9ghz 32GB Ram, Nvidia RTX2060 Kubuntu 22.04-64bit, Windows 10 Pro 64-bit Samsung Series 5, AMD A-6 2.1 GHz 4 Gt Ram, Ubuntu 18.04 64-bit.
Lenovo T60 Core2Duo 2GB Ram Ati Mobility Radeon 128 MB Ubuntu Mate 16.04-64bit
Commodore Amiga 500 1MB Ram.

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: python syöterivin tarkistaminen
« Vastaus #9 : 14.01.21 - klo:18.40 »

Heeh tuli toissa syksynä painittua pythonin, unix-ajan ja perinteisen ajan kanssa. En nyt muista heti kättelyssä minkä ratkaisun kehitin, sen muistan että erillistä valmista moduulia käyteltiin ja sai sitten merkkijonojakin manipuloida urakalla :D

Varmaan mielenkiintoinen harjoitus. Jos löydät jostain harjoitusesitys-ratkaisusi, niin pistä vaikka jakoon, ihan mielenkiintoista olisi nähdä, miten ajan kanssa toimisit.
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

JaniAlander

  • Käyttäjä / moderaattori+
  • Viestejä: 3319
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #10 : 14.01.21 - klo:20.51 »
Se olikin ihan simppeli, datetime moduuli muuntaa näppärästi: datetime.fromtimestamp(epoch)

Yksi toinen harjoituksista tuotti enemmän päänvaivaa datamuunnosten kanssa...tämmöinen simppeli auringonlaskuaikoja tuottava ohjelma (ei toimi ilman api-keytä joka tuosta on obfuskoitu):
import urllib.parse
import requests
import json
from datetime import datetime
import time as time_
from datetime import time, datetime
from timezonefinder import TimezoneFinder
from pytz import timezone, utc
tf=TimezoneFinder()
#riippuvuudet, muista asentaa timezonefinder ja pytz
main_api ="http://www.mapquestapi.com/geocoding/v1/address?"
key = "******"
loc1 = "&location="
print("Anna kaupunki")
locationcity = input()
print("Anna maa englanniksi")
locationcnt = input()
locationcountry = "+"+locationcnt
print("Anna postinumero")
locationzp = input()
locationzip = "+"+locationzp
location =loc1+locationcity+locationcountry+locationzip  #täälysti käsittely palvelupyynnön tuolle geolokaatioapi:lle
url = main_api+key+location
json_data = requests.get(url)
data=json_data.json()
lat2 = data['results'][0]['locations'] #hirmuinen datanpyöritys
lat3 = []
for item in lat2:                       #tääpalauttaa sitten vihdoin sen latitudin ja longitudin
    lat3.append(item['latLng'])
latfinal =[]
for item in lat3:                       #nyt saataan latitudi listana
    latfinal.append(item['lat'])
lngfinal=[]                             #ja longitudi
for item in lat3:
    lngfinal.append(item['lng'])
lat = latfinal[0]                       #syötetään ne
lng = lngfinal[0]
main_api2="https://api.sunrise-sunset.org/json?"
formatted = "1"
url2 = main_api2 +urllib.parse.urlencode({"lat":lat, "lng":lng, "formatted":formatted})
json_data = requests.get(url2).json()
#otetaan nousuaika datasta, muokataan sieltä tunti int:iksi ja muutetaan 24h muotoon
nousuaika = json_data['results']['sunrise']
if len(nousuaika) == 10:
    nousuaika = "0"+nousuaika
nousuaikah=nousuaika[:2]
nousuaikam=nousuaika[3:5]
nousuaikas=nousuaika[6:8]
nousuinth = int(nousuaikah)
noipap= nousuaika[9:]
if noipap == "PM":
    nousuinth = 12+nousuinth
laskuaika = json_data['results']['sunset']
#sama laskuajalle
if len(laskuaika) == 10:
    laskuaika = "0"+laskuaika
laskuaikah=laskuaika[:2]
laskuaikam=laskuaika[3:5]
laskuaikas=laskuaika[6:8]
laskuinth = int(laskuaikah)
laipap= laskuaika[9:]
if laipap == "PM":
    laskuinth = 12+laskuinth
#täällä tapahtuu aikavyöhyketaikuus
today = datetime.now()
tz_target = timezone(tf.certain_timezone_at(lng=lng, lat=lat))
today_target = tz_target.localize(today)
today_utc = utc.localize(today)
offset = (today_utc - today_target).total_seconds() / 3600
nousuaikaloc = int(nousuinth +offset)
nousuaikalocs = str(nousuaikaloc)
print("Aurinko nousee "+nousuaikalocs+":"+nousuaikam+":"+nousuaikas)

laskuaikaloc = int(laskuinth + offset)
laskuaikalocs = str(laskuaikaloc)
print("Aurinko laskee "+laskuaikalocs+":"+laskuaikam+":"+laskuaikas)

Paljon muuttujia mutta no ne oli tarpeen jotta itse pysyi kärryillä ohjelman puuhista...
« Viimeksi muokattu: 14.01.21 - klo:20.56 kirjoittanut JaniAlander »
Core i5-9400F 2.9ghz 32GB Ram, Nvidia RTX2060 Kubuntu 22.04-64bit, Windows 10 Pro 64-bit Samsung Series 5, AMD A-6 2.1 GHz 4 Gt Ram, Ubuntu 18.04 64-bit.
Lenovo T60 Core2Duo 2GB Ram Ati Mobility Radeon 128 MB Ubuntu Mate 16.04-64bit
Commodore Amiga 500 1MB Ram.

nm

  • Käyttäjä
  • Viestejä: 16232
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #11 : 15.01.21 - klo:02.28 »
location =loc1+locationcity+locationcountry+locationzip  #täälysti käsittely palvelupyynnön tuolle geolokaatioapi:lle
url = main_api+key+location
json_data = requests.get(url)
data=json_data.json()
lat2 = data['results'][0]['locations'] #hirmuinen datanpyöritys
lat3 = []
for item in lat2:                       #tääpalauttaa sitten vihdoin sen latitudin ja longitudin
    lat3.append(item['latLng'])
latfinal =[]
for item in lat3:                       #nyt saataan latitudi listana
    latfinal.append(item['lat'])
lngfinal=[]                             #ja longitudi
for item in lat3:
    lngfinal.append(item['lng'])
lat = latfinal[0]                       #syötetään ne
lng = lngfinal[0]

Osoitteen muuntaminen koordinaateiksi onnistuisi helposti GeoPy-kirjaston avulla: https://geopy.readthedocs.io/en/stable/#

#otetaan nousuaika datasta, muokataan sieltä tunti int:iksi ja muutetaan 24h muotoon
nousuaika = json_data['results']['sunrise']
if len(nousuaika) == 10:
    nousuaika = "0"+nousuaika
nousuaikah=nousuaika[:2]
nousuaikam=nousuaika[3:5]
nousuaikas=nousuaika[6:8]
nousuinth = int(nousuaikah)
noipap= nousuaika[9:]
if noipap == "PM":
    nousuinth = 12+nousuinth
laskuaika = json_data['results']['sunset']
#sama laskuajalle
if len(laskuaika) == 10:
    laskuaika = "0"+laskuaika
laskuaikah=laskuaika[:2]
laskuaikam=laskuaika[3:5]
laskuaikas=laskuaika[6:8]
laskuinth = int(laskuaikah)
laipap= laskuaika[9:]
if laipap == "PM":
    laskuinth = 12+laskuinth

dateutil.parser auttaa kellonaikojen ja päivämäärien lukemisessa. Ei kuulu Pythonin standardikirjastoon, mutta on hyvin yleisesti käytetty paketti.

Asennus yhdelle käyttäjälle:
Koodia: [Valitse]
pip3 install --user python-dateutil
Tai koko järjestelmän käyttöön:
Koodia: [Valitse]
sudo pip3 install python-dateutil
Esimerkki:
Koodia: [Valitse]
import dateutil.parser
d = dateutil.parser.parse("5:12:59 PM")  # Palauttaa datetime-objektin
print(d)
Lainaus
2021-01-15 17:12:59

JaniAlander

  • Käyttäjä / moderaattori+
  • Viestejä: 3319
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #12 : 15.01.21 - klo:13.45 »
Noi oli yhden ohjelmointikurssin harjoitustöitä, joissa pääpaino oli ulkoisten api:den käytössä, siksi niitä tuossa koodissa vilisee. Suurin osa hommaa vaan oli muuntaa jonkin api:n tuloste toisen hyväksymään muotoon.
Core i5-9400F 2.9ghz 32GB Ram, Nvidia RTX2060 Kubuntu 22.04-64bit, Windows 10 Pro 64-bit Samsung Series 5, AMD A-6 2.1 GHz 4 Gt Ram, Ubuntu 18.04 64-bit.
Lenovo T60 Core2Duo 2GB Ram Ati Mobility Radeon 128 MB Ubuntu Mate 16.04-64bit
Commodore Amiga 500 1MB Ram.

Tomin

  • Palvelimen ylläpitäjä
  • Käyttäjä / moderaattori+
  • Viestejä: 11433
    • Profiili
    • Tomin kotisivut
Vs: python syöterivin tarkistaminen
« Vastaus #13 : 16.01.21 - klo:17.49 »
Meni tuo obfusikointikeskustelu sen verran pahasti ohi aiheen, että päädyin jakamaan kahtia. Voitte keskustella siitä tuolla:
https://forum.ubuntu-fi.org/index.php?topic=56045.0
Automaattinen allekirjoitus:
Lisäisitkö [RATKAISTU] ketjun ensimmäisen viestin aiheeseen ongelman ratkettua, kiitos.

teele

  • Käyttäjä
  • Viestejä: 809
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #14 : 21.01.21 - klo:13.36 »

Yksi kohta siinä syöterivin tarkistuksessa on päivämäärän tarkistus. Päivämäärä haluttaisiin antaa muodossa vvvvkkpp niin, että tarpeelliset nollat lisätään merkkijonoon ja halutaan, että merkkijonon pituus on aina 8 ja vain tietysti oikeat, todelliset päivämäärät hyväksytään.

Tällaista on kokeiltu

Koodia: [Valitse]
from dateutil.parser import parse
import re

def is_valid_date(d):
    if d and len( re.sub(r'^\s+|\s+$', '', d) ) == 8:
        try:
            parse(d)
            return True
        except:
            return False
    return False


x = input('anna x: ')
while x != 'x':
  print(is_valid_date(x))
  x = input('anna x: ')


Se, onko koodissa joitain porsaanreikiä, joista pääsee syöttämään vääränlaisia päivämääriä, ei ole vielä ihan selvillä. Itsehän omia virheitä ei löydä  :)




SuperOscar

  • Käyttäjä
  • Viestejä: 3993
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: python syöterivin tarkistaminen
« Vastaus #15 : 21.01.21 - klo:13.58 »
”Halutaan antaa” vai ”oletetaan annetuksi”? Jälkimmäinen on helpompi, esimerkiksi:

Koodia: [Valitse]
import re
valid_date = re.compile(r'^(\d\d\d\d)(\d\d)(\d\d)$')

Näin tarkistus kävisi yksinkertaisesti tyyliin valid_date.match('20210121') → palauttaa None ellei ole kelvollinen, muulloin Match-olion.

Sulutuksen ansiosta osat on helppo lukea vuosi-, kuukausi- ja päivämuuttujiksi suoraan .groups()-metodilla:

Koodia: [Valitse]
try:
    year, month, day = valid_date.match(annettu_jono).groups()
except AttributeError:
    print('Virheellinen jono')
« Viimeksi muokattu: 21.01.21 - klo:15.54 kirjoittanut SuperOscar »
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

nm

  • Käyttäjä
  • Viestejä: 16232
    • Profiili
Vs: python syöterivin tarkistaminen
« Vastaus #16 : 21.01.21 - klo:16.36 »
Koodia: [Valitse]
def is_valid_date(d):
    if d and len( re.sub(r'^\s+|\s+$', '', d) ) == 8:
        try:
            parse(d)
            return True
        except:
            return False
    return False

Tuo ei vielä varmista, että syöte on päivämäärä, koska muutkin merkit kuin numerot ovat sallittuja. Dateutil kelpuuttaa silloin esimerkiksi tällaisen kellonajan:

Koodia: [Valitse]
is_valid_date("10:10:30")
True

SuperOscarin ratkaisu on OK numeroiden tarkistamiseen ja erottamiseen, mutta niistä muodostuva päivämäärä pitää vielä validoida kuukausien ja päivien osalta, ja siihen on helpointa käyttää valmista ratkaisua, kuten tuota dateutilin parseria.

Ilman säännöllisiä lausekkeita onnistuisi dateutilin avulla näin:

Koodia: [Valitse]
from dateutil.parser import parse

def is_valid_date(d: str):
    d = d.strip()
    if len(d.strip()) == 8 and d.isdigit():
        try:
            parse(d)
            return True
        except:
            return False
    return False

Myös Pythonin standardikirjaston datetime.strptime soveltuu tähän tapaukseen hyvin, koska syötteen formaatin voi rajata tarkemmin. Senkin kanssa on kuitenkin huomioitava, että formaatti "%Y%m%d" hyväksyy kuukaudet ja päivät sekä etunollan kanssa tai ilman, joten jos haluat validoida, että syötteessä on oikeasti kahdeksan numeroa, se on tehtävä erikseen.

Koodia: [Valitse]
datetime.strptime("202166", "%Y%m%d")
Lainaus
datetime.datetime(2021, 6, 6, 0, 0)

Alla oma ehdotukseni, joka toimii pelkällä standardikirjastolla ja ilman säännöllisiä lausekkeita. Oikeassa tuotantotason toteutuksessa käyttäjälle näkyvä teksti ja virheilmoitukset olisivat koodissa englanniksi ja ne käännettäisiin käyttäjän kielelle esim. gettextin avulla.

Koodia: [Valitse]
from datetime import datetime

def parse_date(datestring: str):
    d = datestring.strip()
    if not (len(d) == 8 and d.isdigit()):
        raise ValueError(f"päivämäärässä '{d}' ei ole kahdeksaa numeroa")
    try:
        return datetime.strptime(d, '%Y%m%d')
    except ValueError as e:
        raise ValueError(f"päivämäärä '{d}' ei täsmää formaattiin VVVVKKPP") from e

dateinput = ''
while dateinput != 'x':
    dateinput = input('Anna päivämäärä: ')
    try:
        dt = parse_date(dateinput)
        print(f'Hyväksytty päivämäärä: {dt}')
    except ValueError as e:
        print(f'Virhe: {e}')
« Viimeksi muokattu: 21.01.21 - klo:16.51 kirjoittanut nm »

teele

  • Käyttäjä
  • Viestejä: 809
    • Profiili
Vs: [ ratkaistu ] python syöterivin tarkistaminen
« Vastaus #17 : 23.01.21 - klo:18.36 »

Tämän säikeen ohjeilla ongelmaan löytyy jopa useita vähän erilaisia ratkaisuja.

Kiitos hyvistä ohjeista  :)