Visualizzazione risultati 1 fino 4 di 4

Discussione: Contare totale risultati tabella in un periodo di tempo

  1. #1
    personalthings non è connesso Utente giovane
    Data registrazione
    10-08-2013
    Messaggi
    73

    Predefinito Contare totale risultati tabella in un periodo di tempo

    Ciao ragazzi, sto iniziando ad avere dei problemi con un codice che fino a settimana scorsa ha sempre funzionato alla perfezione e che non ho più toccato.
    Passo qui di seguito a spiegare sommariamente.
    Il mio sito è composto di diverse chat, le quali hanno uno specifico ID. Il sistema deve prendere tutti i dati raccolti di uno specifico user e, se superiori a 4 in quella specifica chat, viene assegnato un premio. Il premio può essere dato una sola volta al giorno (dunque se dopo aver ricevuto il premio cambio chat e scrivo altre 4 volte, il premio non viene dato, ma bisognerà aspettare il giorno dopo).

    2) La prima cosa che faccio è valorizare la data ultima di quando un utente ha ricevuto il premio:

    Codice PHP:
    $result_premio = query("SELECT last_date_premio FROM user WHERE nome = '".$_SESSION['login']."'");
    $last_date_premio = $result_premio['last_date_premio'];
    2) La seconda cosa che ho fatto, è stabilire il range temporale. Il sistema deve calcolare tutti i risultati che partono dalle 6:00 AM alle 5:59 AM del giorno dopo (e non dalle 00:00 alle 23:59).

    Codice PHP:
    //setto gli estremi temporali//
    $now = time();
    $this_morning = strtotime('today 6:00');
    $last_action = strtotime($last_date_premio);
    3) Da qui parto con il conteggio:

    Codice PHP:
    $check_actions = query("SELECT * FROM windows WHERE id_chat = ". $_SESSION['id_chat'] ." && user = '". $_SESSION['login'] ."' && DATE_ADD(ora, INTERVAL 12 HOUR) >= NOW()", 'result');
    if(
    query($check_actions, 'num_rows') => 4) {
    //vedi spiegazione sotto
    }
    Se i risultati sono superiori o uguali a 4, vedo se il premio non è stato assegnato nel range 6:00-5:59:

    Codice PHP:
    if ($now - $last_action >= (24 * 60 * 60) || ($last_action < $this_morning && $now >= $this_morning))
    {
    //assegno il premio e modifico il campo $last_date_premio a NOW()
    } else {
    //Non assegno nulla perché il premio è già stato dato
    }
    Qui nasce il problema, perché credo non mi riconosca più il range temporale stabilito (6:00-5:59). Siccome non saprei spiegare precisamente il problema, lo illustro fornendo degli esempi:

    28/11/2022

    Inizio conversazione: 22:00
    Quarto risultato: 00:30
    -> Premio assegnato

    29/11/2022

    Inizio conversazione: 21:00
    Quarto risultato: 23:30
    -> Premio NON assegnato (e dovrebbe invece assegnarlo perché rientra nel nuovo giorno (6:00-5:59)

    30/11/2022

    Inizio conversazione: 15:00
    Quarto risultato: 16:30
    -> Premio assegnato (E questo mi fa capire che il problema del 29/11 credo nasca dal premio assegnato dopo la mezzanotte del 28/11)

    C'è per caso un errore nel calcolo del range?
    Ultima modifica di personalthings : 01-12-2022 alle ore 12.00.54

  2. #2
    darbula non è connesso AlterGuru 2500
    Data registrazione
    24-04-2011
    Messaggi
    2,896

    Predefinito

    Utilizzare timezone (fuso orario) Europe/Rome usa datetime con timezone Europe/Rome (nel server mysql) tipo per Mysql
    La funzione time() restituisce Unix timestamp mentre strtotime e date di php dipendono dal valore del timezone.
    Significa time() valore UTC mentre strtotime o date UTC+1 e quando in Europe/Rome cambia l'ora solare siamo UTC+2 :)
    Tuttavia il database altervista mi sembra già Europe/Rome e quindi se memorizzi i campi nel tipo datetime il server mysql non converte la data.
    da time a
    Codice PHP:
    <?php

    date_default_timezone_set
    ('America/Sao_paulo');
    $per_debug = time();
    $variabile = date('Y-m-d H:i:s', $per_debug);
    $rome = $variabile . ' Europe/Rome';
    $strto = strtotime($rome, $per_debug); // Europe/Rome
    var_dump($strto . ' da data precedente America/Sao_paulo a Europe/Rome', $per_debug . ' Unix time', $variabile . ' America/Sao_paulo');
    ?>
    questo esempio mostra che esiste differenza specialmente se ho l'ora con fuso orario differenti.
    Anche php di altervista usa il timezone Europe/Rome ma se usi script può essere modificato inconsapevolmente con codice php (come anche la configurazione mysql).
    Perché non gestire il range tra due date (di tipo datetime Mysql) direttamente in Mysql?
    https://dev.mysql.com/doc/refman/8.0/en/datetime.html "MySQL converte i valori TIMESTAMP dal fuso orario corrente all'ora UTC per l'archiviazione e viceversa dall'ora UTC al fuso orario corrente per il recupero. (Ciò non si verifica per altri tipi come DATETIME.)"
    Ultima modifica di darbula : 02-12-2022 alle ore 11.03.06

  3. #3
    personalthings non è connesso Utente giovane
    Data registrazione
    10-08-2013
    Messaggi
    73

    Predefinito

    Ti chiedo scusa del ritardo ma non avevo visto la tua risposta.
    Anche adottando la tua soluzione, il problema persiste.

    Il problema è sempre il lasso di tempo 00:00-5:59 qualora il giorno prima si sia ricevuto il premio in quella fascia oraria e il giorno dopo lo si riprenda nella stessa.
    Ho la certezza che il bug nasca per la questione mezzanotte. Nello specifico, questo:

    28/11/2022

    Inizio conversazione: 22:00
    Quarto risultato: 00:30 (dunque siamo al 29/11)
    -> Premio assegnato

    29/11/2022

    Inizio conversazione: 21:00
    Quarto risultato: 23:15
    -> Premio NON assegnato (e dovrebbe invece assegnarlo perché rientra nel nuovo giorno (6:00-5:59)

    30/11/2022

    Inizio conversazione: 15:00
    Quarto risultato: 16:30
    -> Premio assegnato (E questo mi fa capire che il problema del 29/11 credo nasca dal premio assegnato dopo la mezzanotte del 28/11)
    Quindi credo che, a questo punto, il problema sia nel calcolo del giorno del 28/11, che il sistema lo valuta come 29 ma che nell'ottica del range temporale appartiene ancora al 28/11 (perché il nuovo giorno l'ho settato dalle 6:00 alle 5:59). Nello specifico, ritengo sia qui:

    Codice PHP:
    //setto gli estremi per il px//
    $now = time();
    $this_morning = strtotime('today 6:00');
    $last_action = strtotime($last_date_premio);

    if (
    $now - $last_action >= (24 * 60 * 60) || ($last_action < $this_morning && $now >= $this_morning)) {

    //assegno il premio
    }
    Sono disperato!
    Come posso specificare che se il premio viene ricevuto dopo la mezzanotte, questo fa parte del giorno prima, perché il giorno "nuovo" deve essere calcolato dalle 6 del mattino?
    Vi prego :(
    Ultima modifica di personalthings : 16-12-2022 alle ore 12.17.07

  4. #4
    darbula non è connesso AlterGuru 2500
    Data registrazione
    24-04-2011
    Messaggi
    2,896

    Predefinito

    Proviamo in questo modo: Europe/Rome attualmente è +01:00 UTC strtotime o date ricordano l'impostazione del timezone predefinito.
    mysql >= 5.7 DATETIME Finché l'impostazione del fuso orario rimane costante, si ottiene lo stesso valore memorizzato.
    Il recupero è quindi costante.
    In php recuperi il valore e poi fai l'aritmetica verso il fuso orario Europe/Rome.
    Codice PHP:
    strtotime($valore_datetime_recuperato_da_sql . ' Europe/Rome'); // esempio non utile ma mostra la differenza tra datetime e l'aritmetica tra numeri
    Adesso il Unix timestamp è calcolato con il fuso orario di Europe/Rome
    Giustamente il valore precedentemente memorizzato nel database sarà il calcolo del periodo valido e cioè dall'ora corrente mysql now() va impostata a domani 2022-17-12 05:59:59 fine vincolo (indipendentemente dal fattore se riscosso premio).
    Tramite php recuperi per valore e fai qualcosa
    Codice PHP:
    <?php
    $valore_datetime_recuperato_da_sql
    = '2022-12-17 05:59:59';
    $var = strtotime($valore_datetime_recuperato_da_sql . ' +1 day Europe/Rome');
    $var = date('Y-m-d H:i:s', $var);
    var_dump($var);
    Se proprio vuoi effettuare l'aritmetica tra date in php altrimenti dal precedente valore memorizzato effettua il calcolo direttamente in mysql tramite la funzione DATE_ADD e l'istruzione SQL per il recupero o comunque per effettuare condizioni o operazioni.
    Non sempre è possibile l'aritmetica manuale perché è più probabile che il fuso orario cambia il valore e che quindi se il fuso orario è +01:00 con l'aritmetica manuale è come se già è un'ora avanti :)
    Ultima modifica di darbula : 16-12-2022 alle ore 15.55.07

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •