Obliczanie czasu pracy na podstawie wprowadzenia godzin

0

Witam,

Chciałbym napisać program do obliczania czasu pracy na podstawie wprowadzenia godziny rozpoczęcia pracy i zakończenia. Starałem się szukać rozwiązania na forach i różnych stronach, ale chyba źle tworzę zapytanie. Czy jest w stanie mi ktoś z tym pomóc. Jedyne co znalazłem to klasa Duration, ale nie jestem pewny czy rozwiązuje ona mój problem.

W konsolę chciałbym wpisać np:
Czas rozpoczęcia pracy : 8:00 lub 8,00
Czas zakończenia pracy : 16:17 lub 16,17

i chodzi mi o liczenie nadgodzin, tak aby dodało mi te 17 minut do salda nadgodzin.

Ogólnie program chcę napisać do przećwiczenia baz danych, a przy okazji będę mógł z niego korzystać w praktyce.

Z góry dziękuję za każdą pomoc i sugestie.

1
jacob8 napisał(a):

Starałem się szukać rozwiązania na forach i różnych stronach, ale chyba źle tworzę zapytanie.

Pytasz o wszystko, więc o nic.

Pakiet java.time, w tym Duration to dobry pomysł, ale przy ogromnej szerokości twojego pytania dalece nie wystarczający, a o bazie danych to nawet jaskółki nie ćwierkają. Jak zrobisz z pierwszym etapie program konsolowy, który przyjmie, doda N rekordów (par) i wydrukuje wynik, to wystarczy.

Sądzę, że nie napalaj się jak szczerbaty na suchary na pełny, użyteczny program z baza danych - głęboko poćwicz elementy. Niestety, proces nauki np. na tokarza, to wiele surowca zmarnowane, tylko na odpad, programowania tak samo.

0
ZrobieDobrze napisał(a):
jacob8 napisał(a):

Starałem się szukać rozwiązania na forach i różnych stronach, ale chyba źle tworzę zapytanie.

Pytasz o wszystko, więc o nic.

Pakiet java.time , w tym Duration to dobry pomysł, ale przy ogromnej szerokości twojego pytania dalece nie wystarczający, a o bazie danych to nawet jaskólki nie ćwierkają
Jak zrobisz z pierwszym etapie program konsolowy, który przyjmie, doda N rekordów (par) i wydrukuje wynik, to wystarczy.

Sądzę, że nie napalaj się jak szczerbaty na suchary na pełny, użyteczny program z baza danych - głęboko poćwicz elementy. Niestey, proces nauki np na tokarza, to wiele surowca zmarnowane, tylko na odpad, programowania tak samo.

O bazie danych to napisałem tak dodatkowo. Chcę wyniki przechowywać w bazie, żeby po ponownym odpaleniu programu suma nadgodzin była zapisana. W tym pości chodzi mi tylko o to jak obliczyć różnicę minut między wprowadzonymi godzinami i wszystko co powyżej 8h pracy zapisać i iterować w zmiennej.

0

Zapisuj to co wprowadzasz jako LocalDateTime a następnie przeczytaj to https://www.baeldung.com/java-date-difference punkt 2.2
Przykład jest dla sekund ale jak pomyślisz to łatwo zrobisz analogicznie dla minut/godzin :)

0

Okej i to już jest cenna informacja. Tylko ten przykład co kolega wyżej podał z LocalDataTime to nie za bardzo wiem jak użyć na moim przykładzie. Zamiana Sekund na minuty to nie ma problemu, ale jak podstawić wprowadzone dane w formie "08:00"? — jacob8 51 sekund temu

Napisać własną klasę i w niej toString()
Podstawy programowania obiektowego.

Bo chyba nie będziesz tego całego g... obliczał w main()

0

Czy jest mi ktoś w stanie napisać jakiś przykład jak to zrobić? Byłbym bardzo wdzięczny ;)

1

Nie. Nikt Ci nie da gotowca.

Ale mogę Ci dać pryzkładowy link https://attacomsian.com/blog/java-convert-string-to-localdatetime (lub dowolny inny ze stacka, ale patrz na date bliżje 2022 niż 2016)
Wprowadzasz jako string w odpowiedniej postaci, a potem parsujesz to na LocalDateTime

0
jacob8 napisał(a):

Czy jest mi ktoś w stanie napisać jakiś przykład jak to zrobić? Byłbym bardzo wdzięczny ;)

Od "zrobię prawie program RCP" do "zróbcie to za mnie" ... ciekawa migracja ...

Zacznijmy: umiesz napisać własną klasę?
a) tak -> to masz piękną okazję (o ile nie opierasz sie na fabrycznej)
b) nie -> to nie ten etap.

0

Tak umiem. I nie chodzi mi o to żeby ktoś mi to wszystko napisał tylko o sam sposób na operacje z użyciem godzin i minut.

Chciałem napisać taki (wydawało mi się prosty) program, żeby przećwiczyć to co się nauczyłem z baz danych + przećwiczyć programowanie obiektowe(takie rzeczy jak dodawanie pracownika i potem wybieranie dla którego obliczać nadgodziny, jakieś statystyki tygodniowe itd) I z tym nie mam problemu tylko napotkałem problem w postaci operacji na godzinach i tylko o ten fragment mi chodzi. Chciałem jakiś jeden działający przykład bo co próbuje podstawić pod te przykłady co mi podrzucił inny użytkownik to nie działa to tak jakbym chciał.

2

Nie pokazałeś żadnego kodu, czyli nawet jeszcze nie zacząłeś tego robić a już widzisz problemy. To niedobrze. Jak chcesz się czegoś nauczyć to mam poradę: nie zaczynaj od komplikowania sobie życia.

W Javie obsługa czasu jest upierdliwa, ale robisz z igły widły. Jeżeli chcesz to faktycznie zrobić z użyciem tylko godziny i minuty to zrób sobie klasę z dwoma polami i metody do dodawania i odejmowania. Podpowiedź: 1 godzina ma 60 minut...

Jak już to ogarniesz - dodaj obsługę daty. Poza samą obsługą pracy zmianowej, o której jeden z Kolegów pisał wyżej zabezpieczy to w jakimś stopniu aplikację przed problemami, które pojawią się kiedy ktoś wprowadzi błędne dane, jakiś czytnik identyfikatorów się zepsuje i nie będzie można zarejestrować wyjścia pracownika itp.

0

Pewnie da sie bardziej elegancko, z formatowaniem wyniku pobaw sie juz sam

public static void main(String[] args) {
    String startTime = "8:30";
    String endTime = "1:00";
    int[] startTimeInt = mapToInt(startTime);
    int[] endTimeInt = mapToInt(endTime);
    
    System.out.println(calculateWorkingTime(startTimeInt[0], startTimeInt[1], endTimeInt[0], endTimeInt[1]));
    }
    
    private static String calculateWorkingTime(int startingHour, int startingMinute, int endingHour, int endingMinute) {
    int minutesDiff = endingMinute - startingMinute;
    int hoursDiff = endingHour - startingHour;
    int hours = 0;
    if (hoursDiff < 0) {
      hours = 24 + hoursDiff;
    }
    return minutesDiff < 0 ?
        hours - 1 + ":" + (60 - Math.abs(minutesDiff)) :
        hours + ":" + minutesDiff;
  }
  
  private static int[] mapToInt(String input) {
    return Arrays.stream(input.split(":"))
        .mapToInt(Integer::valueOf)
        .toArray();
  }
1
jacob8 napisał(a):

Tak umiem. I nie chodzi mi o to żeby ktoś mi to wszystko napisał tylko o sam sposób na operacje z użyciem godzin i minut.

Chciałem napisać taki (wydawało mi się prosty) program, żeby przećwiczyć to co się nauczyłem z baz danych + przećwiczyć programowanie obiektowe(takie rzeczy jak dodawanie pracownika i potem wybieranie dla którego obliczać nadgodziny, jakieś statystyki tygodniowe itd) I z tym nie mam problemu

Skoro tyle osiągnąłeś

tylko napotkałem problem w postaci operacji na godzinach i tylko o ten fragment mi chodzi.

To pozwól że powiem "nie wierzę" , operacje na godzinach to ... (nomem omen) godzina dla kogoś, kto rzeczywiście coś skutecznie programuje
Zeznania kupy się nie trzymają, kodu owych mitycznych prób nie pokazujesz itd ...

1
public class App {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        System.out.print("Wprowadź czas rozpocęcia pracy: ");
        String hourStart = scanner.nextLine();

        System.out.print("Wprowadź czas zakończenia pracy: ");
        String hourEnd = scanner.nextLine();

        countOvertime(hourStart, hourEnd);


    }

    public static void countOvertime(String hourStart, String hourEnd) {

        long overtime;


        LocalDateTime dateTime1 = LocalDateTime.parse(hourStart);

        LocalDateTime dateTime2 = LocalDateTime.parse(hourEnd);

        long diff = ChronoUnit.MINUTES.between(dateTime1, dateTime2);

        String result = LocalTime.MIN.plus(
                Duration.ofMinutes(diff - 30)
        ).toString();

        if (diff > 510L) {
            overtime = (diff - 510L);
        } else if (diff == 510L) {
            overtime = 0;
        } else {
            overtime = diff - 510L;
        }


        System.out.println(result);
        long hours = overtime / 60;
        long minutes = overtime % 60;
        System.out.printf("%d:%02d", hours, minutes);


    }
}

Przy pomocy tych linków udało mi się coś takiego napisać. Wyświetla mi czas pracy w formie "08:31", i nadgodziny w minutach, czyli to czego chciałem. Czyli z tego co zrozumiałem wprowadzania godziny nie da rady uprościć do samej godziny. Data będzie nieodłączna jeśli chce korzystać z LocalDataTime?

Jeśli ma ktoś jeszcze jakiś pomysł jak można to ulepszyć to proszę o info.

Wprowadzam w konsolę:
2023-01-24T15:30
2023-01-25T01:15

Otrzymuję:
09:15
1:15

0

No to teraz zadanie na miarę stażysty java :D

  1. Zrób tak, żeby Twoja funkcja zajmowała się tylko obliczeniami, tj. pozbądź się z niej wyświetlania danych. Dobrze by było gdyby main się tym zajmował, a nie urywał na jakimś count który... nie tylko robi count:
public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);

    System.out.print("Wprowadź czas rozpocęcia pracy: ");
    String hourStart = scanner.nextLine();

    String hourEnd = scanner.nextLine();

    int overtime = countOvertimeMinutes(hourStart, hourEnd);
    System.out.printf("%d:%02d", overtime / 60, overtime % 60);
}
  1. Dodaj komentarze. Nie za dużo, nie za mało.
  2. Co to jest 510L? Zrób z tego stałą i nadaj jej odpowiednią nazwę, żeby nie był potrzebny komentarz.
  3. Następnym etapem powinna być walidacja danych wejściowych, tj. sprawdzenie czy ktoś nie wprowadził niemożliwych do sparsowania danych. Niestety u Ciebie parsowaniem nadal zajmuje się funkcja countOvertime. Proponuję więc przenieść parsowanie na zewnątrz funkcji liczącej, a tą przerobić tak, żeby przyjmowała parametry typu LocalDateTime.

Ja bym zrobił funkcję do pobierania danych typu datetime, żeby w mainie mieć coś w rodzaju:

System.out.print("Wprowadź czas rozpocęcia pracy: ");
LocalDateTime dtStart = readDateTime();

System.out.print("Wprowadź czas zakończenia pracy: ");
LocalDateTime dtEnd = readDateTime();


if (dtStart != null && dtEnd != null) {// sprawdzenie czy wczytaliśmy
    int overtime = countOvertimeMinutes(hourStart, hourEnd);
    System.out.printf("%d:%02d", overtime / 60, overtime % 60);
}

A może nawet funkcja readDateTime mogła też zrobić System.out.print:

LocalDateTime dtStart = readDateTime("Wprowadź czas rozpoczęcia pracy: ");

Wtedy main wyglądał by jakoś tak:

LocalDateTime dtStart = readDateTime("Wprowadź czas rozpocęcia pracy: ");
LocalDateTime dtEnd = readDateTime("Wprowadź czas zakończenia pracy: ");

if (dtStart != null && dtEnd != null) {                          // sprawdzenie czy udało się wczytać cokolwiek
    // można jeszcze sprawdzić, czy wprowadzony czas nie różni się od bieżącej daty o np. więcej niż 3 dni
    int overtime = countOvertimeMinutes(hourStart, hourEnd);
    System.out.printf("%d:%02d", overtime / 60, overtime % 60);  // to można też obudować funkcją która by wyświetlała minuty jako hh:mm
}
1
 public void calculateTimeWork(){
     DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy MM dd HH mm");
     Scanner sc=new Scanner(System.in);
     System.out.println("Podaj czas rozpoczecia pracy  w formacie yyyy MM dd HH mm");

     LocalDateTime start = LocalDateTime.parse(sc.nextLine(),dateTimeFormatter);
     System.out.println("Podaj czas zakaczenia pracy  w formacie yyyy MM dd HH mm");
     LocalDateTime end = LocalDateTime.parse(sc.nextLine(),dateTimeFormatter);
    double duration= Duration.between(start, end).toMinutes();
     System.out.println ( duration/60);
     
                     Ewentualnie zamiast wpisywać czas z klawiatuty mozna użyć.

LocalDateTime.now();

0

@Kamil A: Na podstawie Twojego posta udało mi sie zrobić coś takiego. Zamiast tego if'a w main chciałem zrobić try/catch i złapać wyjątek przy nieodpowiednim wprowadzeniu danych, ale nie wiem czemu nie jestem w stanie tego zrobić bo wtedy podświetla mi "startTime" i "endTime" na czerwono.

public class App {
    public static void main(String[] args) {


        System.out.print("Wprowadź czas rozpocęcia pracy: ");
        LocalDateTime startTime = readDateTime();

        System.out.print("Wprowadź czas zakończenia pracy: ");
        LocalDateTime endTime = readDateTime();

        if (startTime != null && endTime != null) {

            String workTime = countWorkTime(startTime, endTime);
            System.out.println("Czas pracy: " + workTime);

            long overtime = countOvertime(startTime, endTime);
            System.out.printf("Bilans godzin za ten dzień: " + "%d:%02d", overtime / 60, overtime % 60);
        }

    }

    public static long countOvertime(LocalDateTime hourStart, LocalDateTime hourEnd) { // Obliczanie nadgodzin

        long overtime;

        final long MINUTES_PER_DAY = 510L;


        LocalDateTime dateTime1 = hourStart;

        LocalDateTime dateTime2 = hourEnd;

        long diff = ChronoUnit.MINUTES.between(dateTime1, dateTime2);


        if (diff > MINUTES_PER_DAY) {
            overtime = (diff - MINUTES_PER_DAY);
        } else if (diff == MINUTES_PER_DAY) {
            overtime = 0;
        } else {
            overtime = diff - MINUTES_PER_DAY;
        }

        return overtime;

    }

    public static String countWorkTime(LocalDateTime hourStart, LocalDateTime hourEnd) { // Obliczanie czasu pracy


        LocalDateTime dateTime1 = hourStart;

        LocalDateTime dateTime2 = hourEnd;

        long diff = ChronoUnit.MINUTES.between(dateTime1, dateTime2);

        String result = LocalTime.MIN.plus(
                Duration.ofMinutes(diff - 30)
        ).toString();

        return result;
    }

    public static LocalDateTime readDateTime() {

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        Scanner scanner = new Scanner(System.in);

        String time = scanner.nextLine();
        LocalDateTime parsedTime = LocalDateTime.parse(time, dateTimeFormatter);

        return parsedTime;
    }
}


1

Jeśli chcesz to zapisywac do bazy danych i aplikacja jest w pracy to mozesz uzyć
LocalDateTime.now();
zamiast wpisywać recznie.

W obu przypadkach czas będzie się zapisywał automatycznie na podstawie aktualnego czasu .

1 użytkowników online, w tym zalogowanych: 0, gości: 1