Como obter o número da semana em Python?

337

Como descobrir qual número da semana é o ano atual em 16 de junho (wk24) com o Python?

Gerry
fonte
11
@Donal: Um olha para 16 de junho, o outro para 26 de junho.
interjay
5
Definir a semana 1. isocalendar () não é a única maneira de fazê-lo.
Mark10
3
Observe que a saída de strftime("%U", d)pode ser diferente da isocalendar(). Por exemplo, se você mudar o ano para 2004, obterá a semana 24 strftime()e a semana 25 isocalendar().
moooeeeep

Respostas:

408

datetime.datetem um isocalendar()método, que retorna uma tupla contendo a semana do calendário:

>>> import datetime
>>> datetime.date(2010, 6, 16).isocalendar()[1]
24

datetime.date.isocalendar () é um método de instância que retorna uma tupla contendo ano, número da semana e dia da semana na respectiva ordem para a instância de data especificada.

Horst Gutmann
fonte
7
Ajudaria se você explicasse o ' [1]' ou fornecesse um ponteiro para onde procurar as informações.
11138 Jonathan-Leffler
5
Eu acho que o mais fácil é extrair o número da semana usando strftime, melhor import datetime today = datetime.now () semana = today.strftime ( "% W")
bipsa
7
Isso é um pouco tarde. Mas na minha máquina, date(2010, 1, 1).isocalendar()[1]retorna 53. Dos documentos: "Por exemplo, 2004 começa na quinta-feira, portanto, a primeira semana do ano ISO 2004 começa na segunda-feira, 29 de dezembro de 2003 e termina no domingo, 4 de janeiro de 2004, de modo que date(2003, 12, 29).isocalendar() == (2004, 1, 1)e date(2004, 1, 4).isocalendar() == (2004, 1, 7)".
Jclancy
17
isocalendar()é ótimo, mas tenha certeza que é o que você quer. Hoje é um exemplo perfeito. 01/01/2016 é igual a (2015, 53, 5). now.strftime("%W")e now.strftime("%U")são iguais aos 00que muitas vezes é o que se deseja. Exemplos STRFTIME
DaveL17 01/01
bom, acabei de adicionar o dia de hoje eu acho que vai ser útil, era para isso que eu estava procurando: D
Vitaliy Terziev 7/16
123

Você pode obter o número da semana diretamente de datetime como string.

>>> import datetime
>>> datetime.date(2010, 6, 16).strftime("%V")
'24'

Também é possível obter diferentes "tipos" do número da semana do ano alterando o strftimeparâmetro para:

%U- Número da semana do ano (domingo como o primeiro dia da semana) como um número decimal preenchido com zero. Todos os dias em um novo ano anterior ao primeiro domingo são considerados na semana 0. Exemplos: 00 , 01,…, 53

%W- Número da semana do ano ( segunda-feira como o primeiro dia da semana) como um número decimal. Todos os dias em um novo ano anterior à primeira segunda-feira são considerados na semana 0. Exemplos: 00 , 01,…, 53

[...]

( Adicionado no Python 3.6, portado para o Python 2.7 de alguma distribuição ) Várias diretivas adicionais não exigidas pelo padrão C89 estão incluídas por conveniência. Todos esses parâmetros correspondem aos valores de data ISO 8601. Eles podem não estar disponíveis em todas as plataformas quando usados ​​com o strftime()método.

[...]

%V- ISO 8601 semana como um número decimal, com segunda-feira como o primeiro dia da semana. A semana 01 é a semana que contém 4 de janeiro. Exemplos: 01 , 02,…, 53

from: datetime - Tipos básicos de data e hora - documentação do Python 3.7.3

Eu descobri sobre isso a partir daqui . Funcionou para mim no Python 2.7.6

jotacor
fonte
O que você está citando, algum manual do Linux? Python 2.7.5 e 3.3.2 dizem Invalid format stringpara esse padrão. Os documentos deles também não são mencionados %V.
Vsevolod Golovanov
3
Desculpe por não ter mencionado, eu tenho daqui . Funcionou para mim no Python 2.7.6.
Jotacor
2
Ótima resposta! Gostaria de acrescentar que, se você estiver interessado em uma representação '<ANO> - <ISOWEEK>' de suas datas, use em %G-%Vvez de %Y-%V. %Gé o equivalente do ano ISO de%Y
KenHBS 04/07
Eu tive que escrever dessa forma para que funcionasse: datetime.datetime (2010, 6, 16) .strftime ("% V") ou assim datetime.datetime (2010, 6, 16) .date (). Strftime ("% V")
Einar
77

Eu acredito que date.isocalendar()vai ser a resposta. Este artigo explica a matemática por trás do calendário ISO 8601. Confira a parte date.isocalendar () da página de data e hora da documentação do Python.

>>> dt = datetime.date(2010, 6, 16) 
>>> wk = dt.isocalendar()[1]
24

.isocalendar () retorna uma tupla de três com (ano, número da semana, dia da semana). dt.isocalendar()[0]retorna o ano, dt.isocalendar()[1]retorna o número da semana, dt.isocalendar()[2]retorna o dia da semana. Simples como pode ser.

Byron Sommardahl
fonte
4
+1 no link que explica a natureza não intuitiva das semanas ISO.
Mark Ransom
27

Aqui está outra opção:

import time
from time import gmtime, strftime
d = time.strptime("16 Jun 2010", "%d %b %Y")
print(strftime("%U", d))

que imprime 24 .

Consulte: http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior

Bart Kiers
fonte
9
ou% W se suas semanas começarem às segundas-feiras.
ZeWaren
11
Essa abordagem é melhor nos casos em que você não deseja dividir ou converter uma data que vem como uma string ... apenas passe a string em strptime no formato da string e especifique o formato no segundo argumento. Boa solução. Lembre-se:% W se a semana começar às segundas-feiras.
TheCuriousOne
22

A semana ISO sugerida por outras pessoas é boa, mas pode não atender às suas necessidades. Assume que cada semana começa com uma segunda-feira, o que leva a algumas anomalias interessantes no início e no final do ano.

Se você preferir usar uma definição que diga que a semana 1 é sempre de 1 a 7 de janeiro, independentemente do dia da semana, use uma derivação como esta:

>>> testdate=datetime.datetime(2010,6,16)
>>> print(((testdate - datetime.datetime(testdate.year,1,1)).days // 7) + 1)
24
Mark Ransom
fonte
3
Dizer que o isocalendar tem "algumas anomalias interessantes" no início e no final do ano parece um pouco de eufemismo. Os resultados do isocalendar são muito enganadores (mesmo que não estejam realmente incorretos sob a especificação ISO) para alguns valores de data e hora, como 29 de dezembro de 2014, 00:00:00, que de acordo com isocalendar têm um valor de ano de 2015 e uma semanaNúmero de 1 (consulte minha entrada abaixo).
Kevin
3
@ Kevin, não está errado, é só que as definições deles não correspondem às suas. A ISO decidiu duas coisas: primeiro que a semana inteira de segunda a domingo seria no mesmo ano, depois que o ano que continha a maioria dos dias seria o atribuído. Isso leva a dias da semana no início e no final do ano que passam para o ano adjacente.
Mark Ransom
6
Acordado. Mas, pela definição da maioria das pessoas, 29 de dezembro de 2014 definitivamente não será a primeira semana do ano de 2015. Eu só queria chamar a atenção para essa fonte potencial de confusão.
Kevin
Era exatamente isso que eu estava procurando. Não sobre como fazer isso, mas as informações sobre a ISO e começando com a segunda-feira.
Amit Amola 14/05/19
19

Geralmente, para obter o número da semana atual (começa no domingo):

from datetime import *
today = datetime.today()
print today.strftime("%U")
Chaggster
fonte
4
A partir da documentação do strftime ('% U'): "Número da semana do ano (domingo como o primeiro dia da semana) como número decimal [00,53]. Todos os dias em um novo ano anterior ao primeiro domingo são considerados estar na semana 0. "
Dolan Antenucci
14

Para o valor inteiro da semana instantânea do ano, tente:

import datetime
datetime.datetime.utcnow().isocalendar()[1]
user2099484
fonte
10

Existem muitos sistemas para numeração semanal . A seguir, são apresentados os sistemas mais comuns, simplesmente com exemplos de código:

  • ISO : a primeira semana começa na segunda-feira e deve conter o dia 4 de janeiro. O calendário ISO já está implementado no Python:

    >>> from datetime import date
    >>> date(2014, 12, 29).isocalendar()[:2]
    (2015, 1)
  • América do Norte : a primeira semana começa no domingo e deve conter o 1º de janeiro. O código a seguir é minha versão modificada da implementação do calendário ISO do Python para o sistema norte-americano:

    from datetime import date
    
    def week_from_date(date_object):
        date_ordinal = date_object.toordinal()
        year = date_object.year
        week = ((date_ordinal - _week1_start_ordinal(year)) // 7) + 1
        if week >= 52:
            if date_ordinal >= _week1_start_ordinal(year + 1):
                year += 1
                week = 1
        return year, week
    
    def _week1_start_ordinal(year):
        jan1 = date(year, 1, 1)
        jan1_ordinal = jan1.toordinal()
        jan1_weekday = jan1.weekday()
        week1_start_ordinal = jan1_ordinal - ((jan1_weekday + 1) % 7)
        return week1_start_ordinal
    >>> from datetime import date
    >>> week_from_date(date(2014, 12, 29))
    (2015, 1)
  • MMWR (CDC) : a primeira semana começa no domingo e deve conter o dia 4 de janeiro. Criei o pacote epiweeks especificamente para este sistema de numeração (também tem suporte para o sistema ISO). Aqui está um exemplo:
    >>> from datetime import date
    >>> from epiweeks import Week
    >>> Week.fromdate(date(2014, 12, 29))
    (2014, 53)
dralshehri
fonte
8

Se você estiver usando apenas o número da semana isocalendar em todo o quadro, o seguinte deverá ser suficiente:

import datetime
week = date(year=2014, month=1, day=1).isocalendar()[1]

Isso recupera o segundo membro da tupla retornado por isocalendar para o número da semana.

No entanto, se você estiver usando funções de data que tratam do calendário gregoriano, apenas o isocalendar não funcionará! Veja o seguinte exemplo:

import datetime
date = datetime.datetime.strptime("2014-1-1", "%Y-%W-%w")
week = date.isocalendar()[1]

A string aqui diz para retornar a segunda-feira da primeira semana de 2014 como nossa data. Quando usamos o isocalendar para recuperar o número da semana aqui, esperamos obter o mesmo número da semana, mas não o fazemos. Em vez disso, temos um número de semanas de 2. Por quê?

A primeira semana do calendário gregoriano é a primeira semana que contém uma segunda-feira. A primeira semana do isocalendar é a primeira semana que contém uma quinta-feira. A semana parcial no início de 2014 contém uma quinta-feira, portanto, é a primeira semana do isocalendar, edate semana 2.

Se queremos obter a semana gregoriana, precisaremos converter do isocalendar para o gregoriano. Aqui está uma função simples que faz o truque.

import datetime

def gregorian_week(date):
    # The isocalendar week for this date
    iso_week = date.isocalendar()[1]

    # The baseline Gregorian date for the beginning of our date's year
    base_greg = datetime.datetime.strptime('%d-1-1' % date.year, "%Y-%W-%w")

    # If the isocalendar week for this date is not 1, we need to 
    # decrement the iso_week by 1 to get the Gregorian week number
    return iso_week if base_greg.isocalendar()[1] == 1 else iso_week - 1
meesterguyperson
fonte
6

Você pode tentar a diretiva% W como abaixo:

d = datetime.datetime.strptime('2016-06-16','%Y-%m-%d')
print(datetime.datetime.strftime(d,'%W'))

'% W': número da semana do ano (segunda-feira como o primeiro dia da semana) como um número decimal. Todos os dias em um novo ano anterior à primeira segunda-feira são considerados na semana 0. (00, 01, ..., 53)

Tung Nguyen
fonte
2

isocalendar () retorna valores incorretos de ano e número da semana para algumas datas:

Python 2.7.3 (default, Feb 27 2014, 19:58:35) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime as dt
>>> myDateTime = dt.datetime.strptime("20141229T000000.000Z",'%Y%m%dT%H%M%S.%fZ')
>>> yr,weekNumber,weekDay = myDateTime.isocalendar()
>>> print "Year is " + str(yr) + ", weekNumber is " + str(weekNumber)
Year is 2015, weekNumber is 1

Compare com a abordagem de Mark Ransom:

>>> yr = myDateTime.year
>>> weekNumber = ((myDateTime - dt.datetime(yr,1,1)).days/7) + 1
>>> print "Year is " + str(yr) + ", weekNumber is " + str(weekNumber)
Year is 2014, weekNumber is 52
Kevin
fonte
3
Observando alguns links sobre o calendário iso8601 (por exemplo, staff.science.uu.nl/~gent0113/calendar/isocalendar.htm ), vejo que os valores de ano e número de semana retornados por isocalendar () não são "incorretos". Sob a ISO8601, por exemplo, o ano de 2004 começou em 29 de dezembro de 2003. Portanto, isocalendar () pode estar correto ao retornar um ano de 2015 para 29 de dezembro de 2014, mas, para muitos propósitos das pessoas, isso será bastante enganador. .
Kevin
2

Resumo a discussão em duas etapas:

  1. Converta o formato bruto para um datetimeobjeto.
  2. Use a função de um datetimeobjeto ou um dateobjeto para calcular o número da semana.

Aquecer

`` python

from datetime import datetime, date, time
d = date(2005, 7, 14)
t = time(12, 30)
dt = datetime.combine(d, t)
print(dt)

`` ``

1º passo

Para gerar um datetimeobjeto manualmente , podemos usar datetime.datetime(2017,5,3)ou datetime.datetime.now().

Mas, na realidade, geralmente precisamos analisar uma string existente. podemos usar a strptimefunção, como datetime.strptime('2017-5-3','%Y-%m-%d')na qual você precisa especificar o formato. Detalhes de diferentes códigos de formato podem ser encontrados na documentação oficial .

Como alternativa, uma maneira mais conveniente é usar o módulo dateparse . Exemplos são dateparser.parse('16 Jun 2010'), dateparser.parse('12/2/12')oudateparser.parse('2017-5-3')

As duas abordagens acima retornarão um datetimeobjeto.

2º passo

Use o datetimeobjeto obtido para chamar strptime(format). Por exemplo,

`` python

dt = datetime.strptime('2017-01-1','%Y-%m-%d') # return a datetime object. This day is Sunday
print(dt.strftime("%W")) # '00' Monday as the 1st day of the week. All days in a new year preceding the 1st Monday are considered to be in week 0.
print(dt.strftime("%U")) # '01' Sunday as the 1st day of the week. All days in a new year preceding the 1st Sunday are considered to be in week 0.
print(dt.strftime("%V")) # '52' Monday as the 1st day of the week. Week 01 is the week containing Jan 4.

`` ``

É muito complicado decidir qual formato usar. Uma maneira melhor é obter um dateobjeto para chamar isocalendar(). Por exemplo,

`` python

dt = datetime.strptime('2017-01-1','%Y-%m-%d') # return a datetime object
d = dt.date() # convert to a date object. equivalent to d = date(2017,1,1), but date.strptime() don't have the parse function
year, week, weekday = d.isocalendar() 
print(year, week, weekday) # (2016,52,7) in the ISO standard

`` ``

Na realidade, você provavelmente usará date.isocalendar()para preparar um relatório semanal, especialmente na temporada de compras "Natal e Ano Novo".

Yuchao Jiang
fonte
0
userInput = input ("Please enter project deadline date (dd/mm/yyyy/): ")

import datetime

currentDate = datetime.datetime.today()

testVar = datetime.datetime.strptime(userInput ,"%d/%b/%Y").date()

remainDays = testVar - currentDate.date()

remainWeeks = (remainDays.days / 7.0) + 1


print ("Please pay attention for deadline of project X in days and weeks are  : " ,(remainDays) , "and" ,(remainWeeks) , "Weeks ,\nSo  hurryup.............!!!") 
Wael Abo Elhassan
fonte
-1

Muitas respostas foram dadas, mas eu gostaria de adicionar a elas.

Se você precisar que a semana seja exibida como um estilo de ano / semana (por exemplo, 1953 - semana 53 de 2019, 2001 - semana 1 de 2020 etc.), faça o seguinte:

import datetime

year = datetime.datetime.now()
week_num = datetime.date(year.year, year.month, year.day).strftime("%V")
long_week_num = str(year.year)[0:2] + str(week_num)

Vai levar o ano e a semana atuais, e long_week_num no dia da escrita será:

>>> 2006
Simo Todorov
fonte
Por que criar um date()zero? datetime.datetime()instâncias têm um .date()método para esse trabalho.
Martijn Pieters
No entanto, o mais preocupante é que sua resposta escolhe o século , não o ano atual. E se você usará a formatação de seqüência de caracteres para o número da semana, por que não usar isso também para incluir o ano?
Martijn Pieters