Skip to main content
Announcements
Qlik Connect 2024! Seize endless possibilities! LEARN MORE
cancel
Showing results for 
Search instead for 
Did you mean: 
harson
Contributor III
Contributor III

Calcul de durée entre deux Timestamps

Bonjour la communauté,


Je dois calculer l'heure de prise en charge d'un ticket en tenant compte seulement les heures d'ouverture et de fermeture tout les jours .

Example :

             ouverture-fermeture

Lundi : 08h00 - 12h00 et 14h00 - 16h00

Mardi : 08h00 - 11h00 et 16h00 - 20h00

Mercredi : 11h00 - 16h00 et 21h00-Jeudi 08h00

Jeudi : 10h00-15h00 et 20h00-Vendredi 09h00

Samedi : 08h00-12h00

Voici les données

Date_reception                Date_prise_en_charge

06/02/2017 07:00:00        06/02/2017 15:00:00

06/02/2017 21:00:00        07/02/2017 08:30:00

08/02/2017 22:00:00        09/02/2017 07:00:00

09/02/2017 16:00:00        09/02/2017 20:30:00

11/02/2017 11:00:00        13/02/2017 09:00:00

Et j'aimerai avoir les résultats suivant

Date_reception                Date_prise_en_charge                Duree

06/02/2017 07:00:00        06/02/2017 15:00:00                    05:00:00

06/02/2017 21:00:00        07/02/2017 08:30:00                    00:30:00

08/02/2017 22:00:00        09/02/2017 07:00:00                    09:00:00

09/02/2017 16:00:00        09/02/2017 20:30:00                    00:30:00

11/02/2017 11:00:00        13/02/2017 09:00:00                     02:00:00

Quelqu'un a une idée ?


D'avance merci,

1 Solution

Accepted Solutions
sfatoux72
Partner - Specialist
Partner - Specialist

Bonjour Tsiry,

Voici une proposition qui pourra certainement t'aider. J'arrive à obtenir le résultat désiré avec l'expression Durée :

Time(Time#((Count(TimeStamp)-1), 'mm'))

Community_250827.png

En utilisant le script de chargement suivant :

SET TimeFormat='hh:mm:ss';
SET DateFormat='DD.MM.YYYY';
SET TimestampFormat='DD.MM.YYYY hh:mm:ss[.fff]';
SET FirstWeekDay=0;

LET vMinDate = Num(Makedate(2017,2,1));
LET vMaxDate = Num(Makedate(2017,2,28));

ChampDate:
LOAD
      *,
     
WeekDay(Date) as Jour;
LOAD
     
Date($(vMinDate) + (IterNo() -1)) AS Date // Use this one as date 
AUTOGENERATE 1
WHILE Num($(vMinDate) + IterNo() -1) <= Num($(vMaxDate));


// Gestion des jours férié
Left Join(ChampDate)
LOAD Date, Férié as Férié_tmp
INLINE [
     Date, Férié, Desc
     01.05.2017, 1, 1er mai
]
;

Left Join(ChampDate)
Load  Date,
     
if(Férié_tmp=1,1,0) as Férié
Resident ChampDate;

DROP Field Férié_tmp;


// Gestion des horaire d'ouverture par jour
// 0 Lundi --> 6 Dimanche
Horaire:
LOAD *
INLINE [
JourHoraire, DebutHoraire, FinHoraire
      0, 08:00:00, 11:59:00
      0, 14:00:00, 15:59:00
      1, 08:00:00, 10:59:00
      1, 16:00:00, 19:59:00
      2, 11:00:00, 15:59:00
      2, 21:00:00, 23:59:00
      3, 00:00:00, 07:59:00
      3, 10:00:00, 14:59:00
      3, 20:00:00, 23:59:00
      4, 00:00:00, 08:59:00
      5, 08:00:00, 11:59:00
]
;


//Initialisation de la structure
Time:
LOAD *
INLINE [
     Jour, Férié, Time
]
;

LET ligneHoraire = NoOfRows('Horaire');
for i=0 to $(ligneHoraire)-1 // loop through every row

     
LET vJour = Peek('JourHoraire',$(i), 'Horaire');
     
LET vMinTime = Num(Peek('DebutHoraire',$(i), 'Horaire'));
     
LET vMaxTime = Num(Peek('FinHoraire',$(i), 'Horaire'));

     
Concatenate(Time)
     
LOAD
          
$(vJour) as Jour,
           0
as Férié,
          
Time(Time#(Hour(Time($(vMinTime)))*60 + Minute(Time($(vMinTime))) + (IterNo() -1), 'mm'), 'hh:mm:ss') AS Time 
     
AUTOGENERATE 1
     
WHILE Hour(Time($(vMinTime)))*60 + Minute(Time($(vMinTime))) + (IterNo() -1) <= Hour(Time($(vMaxTime)))*60 + Minute(Time($(vMaxTime)));
next

Inner Join(ChampDate)
LOAD *
Resident Time;

DROP Table Time;


Left Join(ChampDate)
LOAD Date, Time,
     
Timestamp(Date + Time) as TimeStamp
Resident ChampDate;

Drop Fields Date, Time;



Ticket:
LOAD *
INLINE [
      Ticket, Date_reception, Date_prise_en_charge
      1, 06.02.2017 07:00:00, 06.02.2017 15:00:00
      2, 06.02.2017 21:00:00, 07.02.2017 08:30:00
      3, 08.02.2017 22:00:00, 09.02.2017 07:00:00
      4, 09.02.2017 16:00:00, 09.02.2017 20:30:00
      5, 11.02.2017 11:00:00, 13.02.2017 09:00:00
]
;


linkTable:
LOAD Ticket,
     
Date_reception as Date_reception_tmp,
     
Date_prise_en_charge as Date_prise_en_charge_tmp
Resident Ticket;

Left Join(linkTable)
IntervalMatch(TimeStamp)
Load Distinct Date_reception_tmp, Date_prise_en_charge_tmp
Resident linkTable;

Drop Fields Date_reception_tmp, Date_prise_en_charge_tmp;

View solution in original post

8 Replies
sfatoux72
Partner - Specialist
Partner - Specialist

Bonjour Tsiry,

Je pense que j'effectuerai les étapes suivantes:

  • Création d'un calendrier à la minute (éventuellement 5, 10, 15, 30 minutes suivant la granularité désirée)
  • Sur cette base, création du calendrier d'ouverture à la minutes
    • Identification de chaque plage horaire avec IntervalMatch
    • Identification des jours fériés pour les filtrer
  • Lier chaque ticket (Date_reception, Date_prise_en_charge) au calendrier d'ouverture à la minute avec IntervalMatch
  • Il est alors possible de calculer la durée par ticket

Ok, c'est pas tout simple et y a du travail, mais je ne vois pas d'autre solution pour l'instant.

harson
Contributor III
Contributor III
Author

Merci Sébastien,

je vais essayer

sfatoux72
Partner - Specialist
Partner - Specialist

Bonjour Tsiry,

Si des réponses vous ont aidés, merci de les spécifier comme "Utile".

Si vous désirez recommander une réponse aux autres membre de la communauté, cliquez sur recommander.

Et si la réponse résout votre problème, merci de mettre la question comme résolue, afin d'aider les autres membres de la communauté.

Merci

sfatoux72
Partner - Specialist
Partner - Specialist

Bonjour Tsiry,

Voici une proposition qui pourra certainement t'aider. J'arrive à obtenir le résultat désiré avec l'expression Durée :

Time(Time#((Count(TimeStamp)-1), 'mm'))

Community_250827.png

En utilisant le script de chargement suivant :

SET TimeFormat='hh:mm:ss';
SET DateFormat='DD.MM.YYYY';
SET TimestampFormat='DD.MM.YYYY hh:mm:ss[.fff]';
SET FirstWeekDay=0;

LET vMinDate = Num(Makedate(2017,2,1));
LET vMaxDate = Num(Makedate(2017,2,28));

ChampDate:
LOAD
      *,
     
WeekDay(Date) as Jour;
LOAD
     
Date($(vMinDate) + (IterNo() -1)) AS Date // Use this one as date 
AUTOGENERATE 1
WHILE Num($(vMinDate) + IterNo() -1) <= Num($(vMaxDate));


// Gestion des jours férié
Left Join(ChampDate)
LOAD Date, Férié as Férié_tmp
INLINE [
     Date, Férié, Desc
     01.05.2017, 1, 1er mai
]
;

Left Join(ChampDate)
Load  Date,
     
if(Férié_tmp=1,1,0) as Férié
Resident ChampDate;

DROP Field Férié_tmp;


// Gestion des horaire d'ouverture par jour
// 0 Lundi --> 6 Dimanche
Horaire:
LOAD *
INLINE [
JourHoraire, DebutHoraire, FinHoraire
      0, 08:00:00, 11:59:00
      0, 14:00:00, 15:59:00
      1, 08:00:00, 10:59:00
      1, 16:00:00, 19:59:00
      2, 11:00:00, 15:59:00
      2, 21:00:00, 23:59:00
      3, 00:00:00, 07:59:00
      3, 10:00:00, 14:59:00
      3, 20:00:00, 23:59:00
      4, 00:00:00, 08:59:00
      5, 08:00:00, 11:59:00
]
;


//Initialisation de la structure
Time:
LOAD *
INLINE [
     Jour, Férié, Time
]
;

LET ligneHoraire = NoOfRows('Horaire');
for i=0 to $(ligneHoraire)-1 // loop through every row

     
LET vJour = Peek('JourHoraire',$(i), 'Horaire');
     
LET vMinTime = Num(Peek('DebutHoraire',$(i), 'Horaire'));
     
LET vMaxTime = Num(Peek('FinHoraire',$(i), 'Horaire'));

     
Concatenate(Time)
     
LOAD
          
$(vJour) as Jour,
           0
as Férié,
          
Time(Time#(Hour(Time($(vMinTime)))*60 + Minute(Time($(vMinTime))) + (IterNo() -1), 'mm'), 'hh:mm:ss') AS Time 
     
AUTOGENERATE 1
     
WHILE Hour(Time($(vMinTime)))*60 + Minute(Time($(vMinTime))) + (IterNo() -1) <= Hour(Time($(vMaxTime)))*60 + Minute(Time($(vMaxTime)));
next

Inner Join(ChampDate)
LOAD *
Resident Time;

DROP Table Time;


Left Join(ChampDate)
LOAD Date, Time,
     
Timestamp(Date + Time) as TimeStamp
Resident ChampDate;

Drop Fields Date, Time;



Ticket:
LOAD *
INLINE [
      Ticket, Date_reception, Date_prise_en_charge
      1, 06.02.2017 07:00:00, 06.02.2017 15:00:00
      2, 06.02.2017 21:00:00, 07.02.2017 08:30:00
      3, 08.02.2017 22:00:00, 09.02.2017 07:00:00
      4, 09.02.2017 16:00:00, 09.02.2017 20:30:00
      5, 11.02.2017 11:00:00, 13.02.2017 09:00:00
]
;


linkTable:
LOAD Ticket,
     
Date_reception as Date_reception_tmp,
     
Date_prise_en_charge as Date_prise_en_charge_tmp
Resident Ticket;

Left Join(linkTable)
IntervalMatch(TimeStamp)
Load Distinct Date_reception_tmp, Date_prise_en_charge_tmp
Resident linkTable;

Drop Fields Date_reception_tmp, Date_prise_en_charge_tmp;

harson
Contributor III
Contributor III
Author

Bonjour Sébastien,

Je vous remercie d'avoir repondu.

J'ai essayé mais je n'obtiens pas le même resultat que vous d'après votre capture ci-dessus.

Ci-joint un QVW de l'essai que j'ai fait.

Cdt,

Tsiry

sfatoux72
Partner - Specialist
Partner - Specialist

C'est étrange,

C'était du à nos différences dans les paramètres d'environnement.

Si tu ajoutes ceci avant mon code ça va fonctionner :

SET DecimalSep='.';
SET TimeFormat='hh:mm:ss';

Il faudra bien sur modifier le code pour qu'il fonctionne avec tes formats de date, time, timestamp

harson
Contributor III
Contributor III
Author

Oui, c'était la ligne SET DecimalSep='.'; qui a causé la différence.

Maintenant c'est bon.

Merci beaucoup Sébastien.

Cdt,

cbavay
Contributor
Contributor

Bonjour, 

Je sais que je déterre un peu ce sujet  mais il vient de bien m'aider pour calculer un nombre de minutes ouvrables entre deux dates.
J'ai apporté une petite modification qui pourrait peut-être aussi aider quelqu'un.

Comme on à le -1, si une date de réception est avant l'heure d'ouverture et que la date de prise en charge est aussi avant l'heure d'ouverture, on a alors aucun enregistrement dans la linktable et du coup le -1 fait qu'on a un résultat qui indique 23h31 alors que le résultat devrait être 00h00 puisque le ticket est ouvert et résolu hors de l'horaire d'ouverture de la société.

Pour tenir compte de ce cas, j'ai ajouté un if :
Originale : 
     Time(Time#((Count(TimeStamp)-1), 'mm'))
Modifiée : 
     Time(Time#(if(Count(TimeStamp)>0,Count(TimeStamp)-1,0), 'mm'))

 

Merci en tout cas pour le code de base qui m'a fortement aidé.

Cédric