Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Ajan pilkkominen

Sivun loppuun

manninen [20.11.2014 23:00:52]

#

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.

Grez [21.11.2014 13:00:31]

#

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.

manninen [21.11.2014 16:03:56]

#

Eli järkevin tapa laskea ajat ovat PHP puolella, silmukassa toteutettuna. Kiitos.

jalski [24.11.2014 11:54:07]

#

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.

manninen [26.11.2014 10:16:07]

#

Kiitoksia, perehdynpä tähänkin vaihtoehtoon paremmin.

jalski [27.11.2014 08:04:34]

#

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

amuse [27.11.2014 13:34:18]

#

Mites sitten kun pitäisi minuutin tarkkuudella aikoja laskea?

jalski [27.11.2014 17:37:13]

#

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ö

jalski [30.11.2014 16:11:51]

#

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

manninen [03.12.2014 17:14:52]

#

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ä.

Eki++ [03.12.2014 17:26:00]

#

Käytä SQL:n tietotyyppiä TIME.

feenix [03.12.2014 19:23:33]

#

Eki++ kirjoitti:

Käytä SQL:n tietotyyppiä TIME.

Ehkä kuitenkin mieluummin INTERVAL, koska kyse on ajan pituudesta, ei kellonajasta.

manninen [03.12.2014 22:11:41]

#

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.

amuse [04.12.2014 21:28:58]

#

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...

manninen [05.12.2014 18:19:30]

#

Kiitoksia kaikille kommentoineille, sain näillä homman pelittämään kuten toivon. Ongelma siltä osin kohdallani ratkaistu.

Hyvää ennnen aikaista joulua!


Sivun alkuun

Vastaus

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

Tietoa sivustosta