Ottieni la data dal numero della settimana


91

Per favore, cosa c'è di sbagliato nel mio codice:

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

Visualizza "2013-01-01 00:00:00", grazie.

Risposte:


182

Un numero di settimana non è sufficiente per generare una data; hai bisogno anche di un giorno della settimana. Aggiungi un valore predefinito:

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

Il modello -1e -%windica al parser di scegliere il lunedì di quella settimana. Questo produce:

2013-07-01 00:00:00

%Wutilizza il lunedì come primo giorno della settimana. Sebbene tu possa scegliere il tuo giorno della settimana, potresti ottenere risultati inaspettati se ti allontani da quello.

Vedere la strftime()e strptime()comportamento sezione nella documentazione, nota 4:

Se utilizzati con il strptime()metodo, %Ue %Wvengono utilizzati solo nei calcoli quando sono specificati il ​​giorno della settimana e l'anno.

Nota, se il numero della tua settimana è una data della settimana ISO , ti consigliamo di usarlo %G-W%V-%u! Quelle direttive richiedono Python 3.6 o più recente.


2
Non funziona. 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 prima e la seconda settimana del 2018 hanno la stessa data di inizio.
ozw1z5

2
@ ozw1z5rd: questo perché non c'è la settimana 0 nel 2018. La settimana 0 è la settimana parziale prima del primo lunedì dell'anno; nel 2018 il primo lunedì è il 1 gennaio. In altre parole, il problema qui è la stringa di input , non la tecnica, e Python ha corretto l'errore per interpretare W0 nel senso invece W1.
Martijn Pieters

@ ozw1z5rd: se questo è un problema per la tua app, avrai bisogno di questi anni in casi speciali; if d.endswith('-W0') and r.day == 7: raise ValueError('Invalid date string, No week 0 in {}'.format(r.year))
Martijn Pieters

Qualche idea su come gestire i numeri delle settimane riempite diversi da zero? (es. 2020-w1, 2020-w52)
Michael H.

@MichaelH .: Non sono sicuro di quello che stai chiedendo.
Martijn Pieters

30

Per completare le altre risposte, se stai usando i numeri della settimana ISO , questa stringa è appropriata (per ottenere il lunedì di un dato numero di settimana ISO):

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

%G, %V, %uSono equivalenti ISO di %Y, %W, %w, quindi questo uscite:

2013-06-24 00:00:00

Disponibile in Python 3.6+; da documenti .


14

In Python 3.8 c'è il pratico datetime.date.fromisocalendar:

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

Nelle versioni precedenti di Python (3.7-) il calcolo può utilizzare le informazioni da datetime.date.isocalendarper calcolare le settimane conformi a ISO8601 della settimana:

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))

Entrambi funzionano anche con datetime.datetime.


7
import datetime
res = datetime.datetime.strptime("2018 W30 w1", "%Y %W w%w")
print res

L'aggiunta di 1 come giorno della settimana restituirà l'inizio esatto della settimana corrente. L'aggiunta di timedelta (giorni = 6) ti darà il fine settimana.

datetime.datetime(2018, 7, 23)

@Senthikumar C che dovrebbe essere come sottores = datetime.datetime.strptime("2018 W30 w1", "%Y W%W w%w")
MD Alauddin Al-Amin,

La risposta accettata ha un problema con la data 2021-01-04, si dice che appartiene all'anno 2020
ignacio.munizaga

1

Se disponi del numero annuale di settimane, aggiungi semplicemente il numero di settimane al primo giorno dell'anno.

>>> 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)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.