Hei!
Ajatellaan, että työntekijä tulee töihin. 20.11.2014 kello 22:59 ja lähtee aamulla 21.11.2014 07:00.
Mikä olisi järkevin tapa lähteä katsomaan mitkä tunneista ovat iltatunteja, mitkä yö ja mitkä ajoittuvat mille päivälle. Ideoita toteutukseen, mikä olisi fiksuin tapa toteuttaa tämän kaltainen toiminto. Tiedot haettaisiin tietokannasta.
Ensin kannattaa selvittää, mitkä on pilkkomisen säännöt. Eli milloin tunti on iltatunti (esim. "arkisin 17 - 21"), milloin yötunti, mitä tarkoitetaan "mille päivälle", siis viikonpäivälle vai jotain muuta. Sitten kannattaa selvittää missä muodossa tiedot pitääs saada ulos. Kun nuo on selivetty niin itse laskennan koodaa ehkä 15 minuutissa.
Toteutuksena voisi olla esimerkiksi silmukka, missä mitä lajia jäljellä oleva aika on, ja milloin ko. aikalaji loppuu. Jos jäljellä oleva aika loppuu ennen aikalajin loppumista niin lisätään jäljellä oleva aika aikalajiin ja poistutaan silmukasta. Muussa tapauksessa lisätään aika vaihtoon asti ja jatketaan silmukassa.
Eli järkevin tapa laskea ajat ovat PHP puolella, silmukassa toteutettuna. Kiitos.
manninen kirjoitti:
Eli järkevin tapa laskea ajat ovat PHP puolella, silmukassa toteutettuna.
Tukeeko PHP bittimerkkijonoja?
Itse tallentaisin jokaisen vuorokauden tehdyt työtunnit bittimerkkijonona. Eli siis hiukan samaan tapaan, kuin yksinkertaisessa paperimallisessa tuntilistassa olisi ruksittuna aina päivän tehdyt tunnit. Homma hoituu määrittämällä bittimaskit päivä, ilta -ja yötunneille sekä tekemällä loogiset bitti-operaatiot silmukassa jokaiselle päivälle palkkajakson aikana ja laskemalla ykkösbittien lukumäärät yhteen kutakin tuntilajiketta kohden.
Kiitoksia, perehdynpä tähänkin vaihtoehtoon paremmin.
manninen kirjoitti:
Kiitoksia, perehdynpä tähänkin vaihtoehtoon paremmin.
Alla vielä yksinkertainen REXX-esimerkki, josta näkee miten bittimerkkijonot helpottavat laskentaa. Esimerkki hakee päivät ja tunnit tekstitiedostosta tietokannan sijaan. Vuorokauden tunnit on siis tallennettu bittimerkkijonona.
esimerkki syötetiedosto:
01.11.2014 000000011111111100000000 02.11.2014 000000011111111100000000 03.11.2014 000000011111111100000000 04.11.2014 000000011110011100000000 05.11.2014 000000000000000011111110 06.11.2014 111111100000000000000000
Tästä saadaan eri tuntilajikkeiden määrät laskettua suoraviivaisesti. Ainoa erikoisemman näköinen kohta listauksessa voi olla bittimerkkijonosta ykkösbittien lukumäärän laskeminen. Teen sen nyt niin, että korvaan merkkijonosta ykkösestä poikkeavat merkit välilyönnillä. Sitten vaan poistan välit ja otan merkkijonosta sen pituuden.
/* REXX */ infile = 'tunnit.txt' daymask = '000000011111111100000000' eveningmask = '000000000000000011111111' nightmask = '111111100000000000000001' summary. = 0 /* Read dates and work hours from input file. */ /* Calculate the number of work hours for dates. */ numlines = 0 do while lines(infile) > 0 numlines = numlines + 1 parse value linein(infile) with d h summary.numlines.date = d summary.numlines.hours = h summary.numlines.dayhours = length(space(translate(bitand(h, daymask), '1', '1'xrange()), 0)) summary.numlines.eveninghours = length(space(translate(bitand(h, eveningmask), '1', '1'xrange()), 0)) summary.numlines.nighthours = length(space(translate(bitand(h, nightmask), '1', '1'xrange()), 0)) end summary.0 = numlines /* Total day, evening and night hours. */ totdh = 0 toteh = 0 totnh = 0 /* Display work hour summary for dates and calculate the total work hours. */ do i=1 for summary.0 say summary.i.date 'päivätunnit: 'summary.i.dayhours, 'iltatunnit: 'summary.i.eveninghours 'yötunnit: 'summary.i.nighthours totdh = totdh + summary.i.dayhours toteh = toteh + summary.i.eveninghours totnh = totnh + summary.i.nighthours end /* Display total work hours. */ say '' say '' say 'TUNNIT YHTEENSÄ:' say '' say 'päivävuoro: 'totdh', iltavuoro: 'toteh', yövuoro: 'totnh exit 0
Ohjelman tulostus esimerkki syötetiedostosta on:
01.11.2014 päivätunnit: 9 iltatunnit: 0 yötunnit: 0 02.11.2014 päivätunnit: 9 iltatunnit: 0 yötunnit: 0 03.11.2014 päivätunnit: 9 iltatunnit: 0 yötunnit: 0 04.11.2014 päivätunnit: 7 iltatunnit: 0 yötunnit: 0 05.11.2014 päivätunnit: 0 iltatunnit: 7 yötunnit: 0 06.11.2014 päivätunnit: 0 iltatunnit: 0 yötunnit: 7 TUNNIT YHTEENSÄ: päivävuoro: 34, iltavuoro: 7, yövuoro: 7
Mites sitten kun pitäisi minuutin tarkkuudella aikoja laskea?
amuse kirjoitti:
Mites sitten kun pitäisi minuutin tarkkuudella aikoja laskea?
Vaatii hiukan enemmän työtä, mutta bittimerkkijonoja pystytään edelleen hyödyntämään:
- Muodostat tehdyistä tunneista bittimerkkijonon, kuten aiemmassa esimerkissä.
- Muodostat tuloleimoista oman bittimerkkijonon.
- Muodostat lähtöleimoista oman bittimerkkijonon.
- Tallennat tulo -ja lähtöleimojen minuutit järjestyksessä erikseen.
Nyt saat bittimaskien avulla eri tuntilajikkeiden aikamäärät laskettua suoraan.
Eli siis lasket tunnit, vähennät tuloleimojen minuutit ja lisäät lähtöleimojen minuutit.
esim.
in out 07:55 16:10 000000011111111000000000 tunnit 000000010000000000000000 tuloleimat 000000000000000100000000 lähtöleimat tulo: 55 lähtö: 10 tehdyt minuutit = tunnit*60 - tulo + lähtö
Laitetaan nyt vielä REXX-esimerkki tuosta minuuttien tarkkuudella työtuntien laskemisestakin.
Tiedot luetaan datatiedostosta. Kyseisessä tiedostossa jokainen päiväys on tallennettu omalle rivilleen. Ensin on aina tallennettu sisäänkirjausaika, sitten tulee '->' ja uloskirjausaika. viimeinen uloskirjausaika voidaan riviltä jättää pois, jos se menee seuraavan vuorokauden puolelle. Vastaavasti myös vuorokauden ensimmäinen sisäänkirjausaika voidaan jättää pois, jolloin oletetaan töiden jatkuvan edellisen vuorokauden puolelta.
esimerkki datatiedosto:
01.11.2014 08:00->10:30 11:00->16:00 02.11.2014 16:00->20:30 21:00-> 03.11.2013 ->02:05
Esimerkkiohjelma:
/* REXX */ infile = 'tunnit.txt' daymask = '000000011111111100000000' eveningmask = '000000000000000011111111' nightmask = '111111100000000000000001' hbits = '000000000000000000000000' summary. = 0 numlines = 0 do while lines(infile) > 0 mins. = 0 line = linein(infile) numlines = numlines + 1 parse value line with pvm line summary.numlines.date = pvm do while line <> '' parse value line with in_hh ':' in_mm '->' out_hh ':' out_mm line if \datatype(in_hh,'N') then do parse var in_hh with '->'out_hh out_mm = in_mm in_hh = '00' in_mm = '00' end if out_hh = '' then do out_hh = '24' out_mm = '00' end else mins.[out_hh+1] = mins.[out_hh+1] + out_mm mins.[in_hh+1] = mins.[in_hh+1] - in_mm hours = overlay(copies('1',out_hh - in_hh), hbits, in_hh + 1) summary.numlines.dayhours = summary.numlines.dayhours, + length(space(translate(bitand(hours, daymask), '1', '1'xrange()), 0)) summary.numlines.eveninghours = summary.numlines.eveninghours, + length(space(translate(bitand(hours, eveningmask), '1','1'xrange()), 0)) summary.numlines.nighthours = summary.numlines.nighthours, + length(space(translate(bitand(hours, nightmask), '1', '1'xrange()), 0)) end mm = 0 do i=1 for 24 if substr(daymask, i, 1) = '1' then mm = mm + mins.i end mm = mm + 60*summary.numlines.dayhours summary.numlines.dayhours = mm%60 summary.numlines.daymins = mm//60 mm = 0 do i=1 for 24 if substr(eveningmask, i, 1) = '1' then mm = mm + mins.i end mm = mm + 60*summary.numlines.eveninghours summary.numlines.eveninghours = mm%60 summary.numlines.eveningmins = mm//60 mm = 0 do i=1 for 24 if substr(nightmask, i, 1) = '1' then mm = mm + mins.i end mm = mm + 60*summary.numlines.nighthours summary.numlines.nighthours = mm%60 summary.numlines.nightmins = mm//60 end summary.0 = numlines say 'TEHDYT TYÖTUNNIT:' do i=1 for summary.0 say summary.i.date 'päivä:' right(summary.i.dayhours,2,'0') 'h' right(summary.i.daymins,2,'0') 'min,', 'ilta:' right(summary.i.eveninghours,2,'0') 'h' right(summary.i.eveningmins,2,'0') 'min,', 'yö:' right(summary.i.nighthours,2,'0') 'h' right(summary.i.nightmins,2,'0') 'min' end exit 0
Ohjelman esimerkki tulostus:
TEHDYT TYÖTUNNIT: 01.11.2014 päivä: 07 h 30 min, ilta: 00 h 00 min, yö: 00 h 00 min 02.11.2014 päivä: 00 h 00 min, ilta: 07 h 30 min, yö: 01 h 00 min 03.11.2013 päivä: 00 h 00 min, ilta: 00 h 00 min, yö: 02 h 05 min
Tässä on nyt ollut paljon puhetta kelloajan pilkkomisesta, eli tunnit saisi laskettua automaattisesti.
Miten kannattaa toimia tilanteessa, jossa tuntien syöttö jää käyttäjän vastuulle. 1h 30 min
1h 45 min
Mikä kenttä tietokantaan kannattaa luoda ja millä tavalla tieto kantaan tallentaa Itse ajattelin decimaalikenttää, mutta silloin voisi syöttää esim 1 h 80 min. Olisiko tälläiseen ratkaisuun toteutusideoita / vinkkejä.
Käytä SQL:n tietotyyppiä TIME
.
Eki++ kirjoitti:
Käytä SQL:n tietotyyppiä
TIME
.
Ehkä kuitenkin mieluummin INTERVAL
, koska kyse on ajan pituudesta, ei kellonajasta.
Lähdin kuitenkin kokeilemaan tuota TIME arvoa, sillä se palvelee minua hyvin.
Törmäsin tämän mötä kuitenkin seuraavanlaiseen ongelmaan, tunteja laskiessa vain ensimmäiset tunnit : ennen, lasketaan. Millä tavalla tämä laskutoimitus tulisi toteuttaa niin, että huomioitaisiin myös : jälkeen olevat minuutit.
TIME on kyllä aivan väärä arvo tuohon. Käytä suosiolla INTERVAL:ia, eli tallenna kantaan esim minuuttien määrä (1:30 = 90). Näin pystyt jatkossa tekemään noita laskutoimituksiakin...
Kiitoksia kaikille kommentoineille, sain näillä homman pelittämään kuten toivon. Ongelma siltä osin kohdallani ratkaistu.
Hyvää ennnen aikaista joulua!
Aihe on jo aika vanha, joten et voi enää vastata siihen.