2
votes

Oracle - Comment obtenir la date de YEAR, WEEKNUM et WEEKDAY?

J'ai besoin de trouver la date d'une année, d'une semaine et d'un jour de la semaine dans oracle. Existe-t-il une fonction intégrée pour cela dans oracle? ou comment puis-je y parvenir?

Ex: Si Année = 2019, Semaine = 22, Jour = 2 (mardi), alors la date doit être «28-05-2019».


1 commentaires

Comment définissez-vous "Semaine" - il existe plusieurs définitions, voir Numérotation des semaines


3 Réponses :


2
votes

En supposant que "Semaine" et "Année" désignent la semaine et l'année selon ISO-8601 vous pouvez utiliser cette fonction:

CREATE OR REPLACE FUNCTION ISOWeekDate(YEAR INTEGER, WEEK INTEGER, DAY INTEGER) RETURN DATE DETERMINISTIC IS
    res DATE;
BEGIN
    IF WEEK > 53 OR WEEK < 1 THEN
        RAISE VALUE_ERROR;      
    END IF;

    res := NEXT_DAY(TO_DATE( YEAR || '0104', 'YYYYMMDD' ) - INTERVAL '7' DAY, 'MONDAY') + ( WEEK - 1 ) * 7;

    IF TO_CHAR(res, 'fmIYYY') = YEAR THEN
        RETURN res + DAY - 1;
    ELSE
        RAISE VALUE_ERROR;
    END IF;
END ISOWeekDate;


0 commentaires

1
votes

Je pense qu'il n'y a pas de fonction intégrée pour cela, vous devrez en créer une vous-même. Voici l'une des solutions que vous pouvez utiliser.

WITH FUNCTION getDate(p_year IN NUMBER, p_weeks IN NUMBER, p_day in NUMBER) RETURN DATE
IS
  v_tmp date;
  v_day number;
BEGIN
  v_tmp := to_date('01/01/'||to_char(p_year),'dd/mm/yyyy'); 
  v_day := to_char(v_tmp,'D');

  RETURN v_tmp+(p_weeks-1)*7+p_day-(v_day)+1;
END;
SELECT getDate(2019,22,2)
FROM DUAL;
/

Selon mes paramètres NLS_TERRITORY, Oracle numérote le jour de la semaine à partir du dimanche, mais d'après votre exemple, vous semblez envisager Lundi comme jour 1 de la semaine. Donc, le même ajustement est apporté à la fonction pour renvoyer le résultat attendu.

De plus, veuillez noter qu'avec la fonction de clause est une nouvelle fonctionnalité d'Oracle 12c, si vous utilisez une ancienne version d'Oracle, vous devrez créer la fonction stockée avant de l'appeler.


7 commentaires

"Oracle numérote le jour de la semaine à partir du dimanche" n'est pas correct. Cela dépend du paramètre NLS_TERRITORY de la session utilisateur actuelle.


Je n'étais pas au courant. Merci, @WernfriedDomscheit pour la clarification.


Cette fonction ne fonctionne pas pour toutes les dates. Par exemple, 2016-W52 correspond à la semaine du 2016-12-26 au 2017-01-01 (selon ISO 8601). getDate (2016,52,2) renvoie 2016-12-20 mais cela devrait être 2016-12-27


Je pense que cela dépend de la façon dont nous numérotons une semaine de l'année. Peu de sites Web considèrent le 28 décembre 2015 au 3 janvier 2016 comme la semaine 53 de l'année 2015.Si tel est le cas, la semaine 52 serait du 26 décembre 2016 au 1 janvier 2017. Mais si nous considérons la semaine du 01-Jan-2016 comme la première semaine de la journée, quel que soit le jour, la semaine 52 serait du 19-Dec-2016 au 25-Dec-2016.


Excel a également une fonction WEEKNUM pour renvoyer le numéro de semaine d'une date spécifique, il renvoie également 20-12-2016 comme semaine 52. WEEKNUM ("20-dec-2016")


Oui, c'est la raison de ma première question Comment définissez-vous "Semaine" - qui est toujours sans réponse.


Je pense que pour que les entrées et les sorties de l'exemple donné soient satisfaites, les critères ci-dessous doivent être remplis. 1. Commencez la numérotation des semaines à partir de la semaine du 01 janvier, quel que soit le jour. 2. Les jours d'une semaine doivent être numérotés à partir du lundi au lieu du dimanche.



0
votes

Logiquement, le numéro de semaine ISO correspond à l'occurrence des jeudis dans cette année civile (grégorienne). L'année ISO d'une semaine ISO est l'année grégorienne dans laquelle tombe le jeudi de cette semaine ISO.

Dans le schéma ISO, les semaines contiennent toujours 7 jours. Les semaines commencent un lundi, se terminent un dimanche et les jours de cette semaine sont numérotés de 1 à 7.

Ce schéma de numérotation des jours de semaine diffère souvent de celui renvoyé par les fonctions WEEKDAY intégrées et similaires dans différents logiciels (ou nécessite des paramètres de base de données particuliers), ce dont il faut être conscient. Vous aurez besoin d'une fonction disponible qui renvoie le jour de la semaine d'une date particulière selon le schéma de numérotation ISO.

Le premier jeudi de l'année peut avoir lieu n'importe où entre le 1er janvier et le 7 janvier.

Si le premier jeudi tombe du 01 janvier, la première semaine ISO de cette année inclura les jours (29/31-décembre) de l'année grégorienne précédente.

Si le premier jeudi tombe le 07-janvier, la dernière semaine ISO de l'année grégorienne précédente inclura les jours (01/03-janvier) de l'année grégorienne en cours.

Si le premier jeudi tombe le 04 janvier, la première semaine ISO de l'année se déroule implicitement du lundi 01 janvier.

Pour concevoir un algorithme, l'approche la plus simple est probablement d'établir à quel jour de la semaine tombe le 04-janvier de l'année donnée, puis d'appliquer le calcul suivant 4 - jour de la semaine . Si le jour de la semaine du 04 janvier est jeudi, le résultat sera 0. Si c'est lundi, le résultat sera 3 (4-1). Si c'est dimanche, le résultat sera -3 (4-7). Nous stockerons ce décalage pour une utilisation après l'étape suivante.

Nous pouvons dériver un décalage provisoire du jour de l'année à partir des numéros de semaine et de jour ISO comme suit: (((iso_week - 1) * 7) - (4 - iso_day)) .

Nous appliquons ensuite le décalage dérivé de la première étape pour le décalage final du jour de l'année. Il s'agit d'un décalage par rapport au 4 janvier de l'année grégorienne donnée. Ce décalage peut être un chiffre négatif si le jour concerné tombe avant le 04 janvier de l'année donnée.

Étant donné ce décalage du jour de l'année, nous pouvons ensuite utiliser des fonctions intégrées pour produire le 04 janvier de l'année donnée, et appliquer le décalage du jour de l'année pour produire la date grégorienne finale.

Par exemple, étant donné 2019-W01-1.

Le 04/01/2019 est un vendredi, donc le jour de la semaine est 5. Le résultat de la première étape est -1 (4-5). Le résultat de la deuxième étape est -3 (((1-1) * 7) - (4-1)). Ajouté ensemble, ils produisent un décalage de jour de l'année de -4. 04-Jan-2019 compensé par -4 résultats au 31-Dec-2018.

Et c'est notre résultat: 2019-W01-1 = 2018-12-31.


0 commentaires