Obtenir la date du numéro de semaine

88

S'il vous plaît, quel est le problème avec mon code:

import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d, "%Y-W%W")
print(r)

Affichez "2013-01-01 00:00:00", merci.

Ali SAID OMAR
la source

Réponses:

175

Un numéro de semaine ne suffit pas pour générer une date; vous avez également besoin d'un jour de la semaine. Ajoutez une valeur par défaut:

import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d + '-1', "%Y-W%W-%w")
print(r)

Le modèle -1et -%windique à l'analyseur de sélectionner le lundi de cette semaine. Cela produit:

2013-07-01 00:00:00

%Wutilise le lundi comme premier jour de la semaine. Bien que vous puissiez choisir votre propre jour de semaine, vous pouvez obtenir des résultats inattendus si vous vous en écartez.

Voir la section strftime()et strptime()comportement dans la documentation, note de bas de page 4:

Lorsqu'elles sont utilisées avec la strptime()méthode, %Uet %Wne sont utilisées dans les calculs que lorsque le jour de la semaine et l'année sont spécifiés.

Notez que si votre numéro de semaine est une date de semaine ISO , vous voudrez l'utiliser à la %G-W%V-%uplace! Ces directives nécessitent Python 3.6 ou plus récent.

Martijn Pieters
la source
J'aimerais pouvoir vous donner plus d'un vote ... Je me cognais la tête pour comprendre pourquoi cela ne fonctionnait pas.
Islam Q.
2
Ne marche pas. datetime.datetime.strptime ("2018-W0-0", "% YW% W-% w") == datetime.datetime.strptime ("2018-W1-0", "% YW% W-% w") -> "2018-01-07 00:00:00". La 1ère et la 2ème semaine de 2018 ont la même date de début.
ozw1z5rd
2
@ ozw1z5rd: c'est parce qu'il n'y a pas de semaine 0 en 2018. La semaine 0 est la semaine partielle avant le premier lundi de l'année; en 2018, le premier lundi est le 1er janvier. En d'autres termes, votre chaîne d'entrée est le problème ici, pas la technique, et Python a corrigé l'erreur pour interpréter W0 comme signifiant W1 à la place.
Martijn Pieters
@ ozw1z5rd: S'il s'agit d'un problème pour votre application, vous devrez faire un cas particulier de ces années; if d.endswith('-W0') and r.day == 7: raise ValueError('Invalid date string, No week 0 in {}'.format(r.year))
Martijn Pieters
1
@darda: Python 3.6 prend déjà en charge les définitions de semaine ISO 8601, l'utilisation %G(année pour la plus grande partie de la semaine) et %Vdans ce cas.
Martijn Pieters
27

Pour compléter les autres réponses - si vous utilisez des numéros de semaine ISO , cette chaîne est appropriée (pour obtenir le lundi d'un numéro de semaine ISO donné):

import datetime
d = '2013-W26'
r = datetime.datetime.strptime(d + '-1', '%G-W%V-%u')
print(r)

%G, %V, %uSont équivalents ISO de %Y, %W, %w, de sorte que cette sortie:

2013-06-24 00:00:00

Disponible en Python 3.6+; à partir de documents .

Luka Kikelj
la source
14

Dans Python 3.8, il y a le pratique datetime.date.fromisocalendar:

>>> from datetime import date
>>> date.fromisocalendar(2020, 1, 1)  # (year, week, day of week)
datetime.date(2019, 12, 30, 0, 0)

Dans les anciennes versions de Python (3.7-), le calcul peut utiliser les informations de datetime.date.isocalendarpour déterminer la semaine des semaines conformes à ISO8601:

from datetime import date, timedelta

def monday_of_calenderweek(year, week):
    first = date(year, 1, 1)
    base = 1 if first.isocalendar()[1] == 1 else 8
    return first + timedelta(days=base - first.isocalendar()[2] + 7 * (week - 1))

Les deux fonctionnent également avec datetime.datetime.

Jens W. Klein
la source
6
import datetime
res = datetime.datetime.strptime("2018 W30 w1", "%Y %W w%w")
print res

L'ajout de 1 comme jour de la semaine donnera le début exact de la semaine en cours. L'ajout de timedelta (jours = 6) vous donnera le week-end.

datetime.datetime(2018, 7, 23)
Senthilkumar C
la source
@Senthikumar C qui devrait être comme cires = datetime.datetime.strptime("2018 W30 w1", "%Y W%W w%w")
MD Alauddin Al-Amin
1

Si vous avez le nombre annuel de semaines, ajoutez simplement le nombre de semaines au premier jour de l'année.

>>> import datetime
>>> from dateutil.relativedelta import relativedelta

>>> week = 40
>>> year = 2019
>>> date = datetime.date(year,1,1)+relativedelta(weeks=+week)
>>> date
datetime.date(2019, 10, 8)
dimosbele
la source
0

Voici une fonction pratique comprenant le problème de la semaine zéro.

Ron
la source