Bagaimana cara mendapatkan angka minggu dalam Python?

339

Bagaimana cara mengetahui nomor minggu tahun ini pada 16 Juni (wk24) dengan Python?

Gerry
sumber
1
@ Donal: Satu melihat pada 16 Juni, yang lain pada 26 Juni.
interjay
5
Tentukan minggu 1. isocalendar () bukan satu-satunya cara untuk melakukannya.
Mark Tolonen
3
Perhatikan bahwa output dari strftime("%U", d)mungkin berbeda dari isocalendar(). Misalnya, jika Anda mengubah tahun ke 2004 Anda akan mendapatkan 24 minggu menggunakan strftime()dan 25 minggu menggunakan isocalendar().
moooeeeep

Jawaban:

409

datetime.datememiliki isocalendar()metode, yang mengembalikan tuple yang berisi minggu kalender:

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

datetime.date.isocalendar () adalah metode instance yang mengembalikan tuple yang berisi tahun, jumlah hari kerja dan hari kerja dalam urutan masing-masing untuk instance tanggal yang diberikan.

Horst Gutmann
sumber
7
Akan membantu jika Anda menjelaskan ' [1]', atau memberi petunjuk ke mana harus mencari informasi.
Jonathan Leffler
5
Saya kira yang paling mudah adalah mengekstrak angka minggu menggunakan strftime, impor datetime terbaik hari ini = datetime.now () week = today.strftime ("% W")
bipsa
7
Ini sedikit terlambat. Tetapi di komputer saya, date(2010, 1, 1).isocalendar()[1]kembali 53. Dari dokumen: "Misalnya, 2004 dimulai pada hari Kamis, jadi minggu pertama ISO tahun 2004 dimulai pada hari Senin, 29 Desember 2003 dan berakhir pada hari Minggu, 4 Januari 2004, jadi itu date(2003, 12, 29).isocalendar() == (2004, 1, 1)dan date(2004, 1, 4).isocalendar() == (2004, 1, 7)."
jclancy
17
isocalendar()memang hebat, tapi pastikan itu yang Anda inginkan. Hari ini adalah contoh sempurna. 01/01/2016 sama dengan (2015, 53, 5). now.strftime("%W")dan now.strftime("%U")sama dengan 00apa yang sering diinginkan. Contoh STRFTIME
DaveL17
bagus, saya baru saja menambahkan hari sekarang saya pikir itu akan membantu, itu adalah apa yang saya serching untuk: D
Vitaliy Terziev
124

Anda bisa mendapatkan nomor minggu langsung dari datetime sebagai string.

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

Anda juga bisa mendapatkan "tipe" berbeda dari jumlah minggu dalam setahun mengubah strftimeparameter untuk:

%U- Nomor minggu dalam setahun (Minggu sebagai hari pertama dalam seminggu) sebagai angka desimal nol empuk. Semua hari dalam tahun baru sebelum hari Minggu pertama dianggap dalam minggu ke 0. Contoh: 00 , 01,…, 53

%W- Nomor minggu dalam setahun ( Senin sebagai hari pertama dalam seminggu) sebagai angka desimal. Semua hari dalam tahun baru sebelum Senin pertama dianggap dalam minggu ke-0. Contoh: 00 , 01,…, 53

[...]

( Ditambahkan dalam Python 3.6, di-backport ke beberapa distribusi Python 2.7's ) Beberapa arahan tambahan yang tidak diperlukan oleh standar C89 disertakan untuk kenyamanan. Semua parameter ini sesuai dengan nilai tanggal ISO 8601. Ini mungkin tidak tersedia di semua platform saat digunakan dengan strftime()metode ini.

[...]

%V- ISO 8601 minggu sebagai angka desimal dengan Senin sebagai hari pertama dalam seminggu. Minggu 01 adalah minggu yang mengandung 4 Januari. Contoh: 01 , 02,…, 53

from: datetime - Jenis tanggal dan waktu dasar - Dokumentasi Python 3.7.3

Saya sudah mengetahuinya dari sini . Ini bekerja untuk saya di Python 2.7.6

jotacor
sumber
Apa yang Anda kutip, beberapa manual Linux? Python 2.7.5 dan 3.3.2 mengatakan Invalid format stringpola ini. Dokumen mereka juga tidak menyebutkan %V.
Vsevolod Golovanov
3
Maaf saya tidak menyebutkannya, saya dapat dari sini . Ini bekerja untuk saya di Python 2.7.6.
jotacor
2
Jawaban bagus! Saya ingin menambahkan bahwa jika Anda tertarik dengan representasi '<Tahun> - <ISOWEEK>' dari tanggal Anda, gunakan %G-%Vsebagai ganti %Y-%V. %Gadalah tahun ISO yang setara dengan%Y
KenHBS
Saya harus menulis seperti ini agar berfungsi: datetime.datetime (2010, 6, 16) .strftime ("% V"), atau seperti datetime.datetime ini (2010, 6, 16) .date (). Strftime ("% V")
Einar
77

Saya percaya date.isocalendar()akan menjadi jawabannya. Artikel ini menjelaskan matematika di balik Kalender ISO 8601. Periksa bagian date.isocalendar () dari halaman datetime dokumentasi Python.

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

.isocalendar () mengembalikan 3-tuple dengan (tahun, minggu num, hari minggu). dt.isocalendar()[0]mengembalikan tahun, dt.isocalendar()[1]mengembalikan jumlah minggu, dt.isocalendar()[2]mengembalikan hari minggu. Sesederhana mungkin.

Byron Sommardahl
sumber
4
+1 untuk tautan yang menjelaskan sifat non-intuitif ISO minggu.
Mark Ransom
27

Ini pilihan lain:

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

yang mencetak 24.

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

Bart Kiers
sumber
9
atau% W jika minggu Anda dimulai pada hari Senin.
ZeWaren
1
Pendekatan ini lebih baik dalam kasus di mana Anda tidak ingin membagi atau mengonversi tanggal yang datang sebagai string ... cukup masukkan string dalam strptime dalam format string apa adanya dan tentukan format dalam argumen kedua. Solusi yang bagus Ingat:% W jika minggu dimulai pada hari Senin.
TheCuriousOne
22

Minggu ISO yang disarankan oleh orang lain adalah yang baik, tetapi mungkin tidak sesuai dengan kebutuhan Anda. Diasumsikan setiap minggu dimulai dengan hari Senin, yang mengarah ke beberapa anomali menarik di awal dan akhir tahun.

Jika Anda lebih suka menggunakan definisi yang mengatakan minggu 1 selalu 1 Januari hingga 7 Januari, terlepas dari hari dalam seminggu, gunakan derivasi seperti ini:

>>> testdate=datetime.datetime(2010,6,16)
>>> print(((testdate - datetime.datetime(testdate.year,1,1)).days // 7) + 1)
24
Mark tebusan
sumber
3
Mengatakan bahwa isocalendar memiliki "beberapa anomali yang menarik" pada awal dan akhir tahun tampaknya sedikit meremehkan. Hasil isocalendar sangat menyesatkan (bahkan jika tidak benar-benar salah di bawah spesifikasi ISO) untuk beberapa nilai waktu, seperti 29 Desember 2014, 00:00:00, yang menurut isocalendar memiliki nilai tahun 2015 dan satu mingguJumlah 1 (lihat entri saya di bawah ini).
Kevin
3
@ Kevin, tidak salah, hanya saja definisi mereka tidak cocok dengan Anda. ISO memutuskan dua hal: pertama bahwa seluruh minggu Senin hingga Minggu akan di tahun yang sama, kedua bahwa tahun yang mengandung sebagian besar hari akan menjadi yang ditugaskan. Ini mengarah ke hari-hari dalam seminggu di sekitar awal dan akhir tahun yang pindah ke tahun yang bersebelahan.
Mark Ransom
6
Sepakat. Tetapi menurut definisi kebanyakan orang, 29 Desember 2014 pasti bukan minggu ke-1 tahun 2015. Saya hanya ingin menarik perhatian pada sumber kebingungan yang potensial ini.
Kevin
Ini persis apa yang saya cari. Bukan tentang bagaimana melakukan ini, tetapi informasi mengenai ISO dan mulai dengan hal Senin.
Amit Amola
19

Umumnya untuk mendapatkan nomor minggu ini (mulai dari hari Minggu):

from datetime import *
today = datetime.today()
print today.strftime("%U")
Chaggster
sumber
4
Dari dokumentasi strftime ('% U'): "Nomor minggu dalam setahun (Minggu sebagai hari pertama dalam seminggu) sebagai angka desimal [00,53]. Semua hari di tahun baru sebelum Minggu pertama dianggap berada di minggu 0. "
Dolan Antenucci
14

Untuk nilai integer dari minggu instan dalam setahun coba:

import datetime
datetime.datetime.utcnow().isocalendar()[1]
pengguna2099484
sumber
10

Ada banyak sistem untuk penomoran minggu . Berikut ini adalah sistem yang paling umum dengan contoh kode:

  • ISO : Minggu pertama dimulai dengan hari Senin dan harus mengandung tanggal 4 Januari. Kalender ISO sudah diterapkan dalam Python:

    >>> from datetime import date
    >>> date(2014, 12, 29).isocalendar()[:2]
    (2015, 1)
  • Amerika Utara : Minggu pertama dimulai dengan hari Minggu dan harus berisi tanggal 1 Januari. Kode berikut adalah versi modifikasi saya dari implementasi kalender ISO Python untuk sistem Amerika Utara:

    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) : Minggu pertama dimulai dengan hari Minggu dan harus mengandung tanggal 4 Januari. Saya membuat paket epiweeks khusus untuk sistem penomoran ini (juga memiliki dukungan untuk sistem ISO). Berikut ini sebuah contoh:
    >>> from datetime import date
    >>> from epiweeks import Week
    >>> Week.fromdate(date(2014, 12, 29))
    (2014, 53)
dralshehri
sumber
8

Jika Anda hanya menggunakan nomor minggu isocalendar di seluruh papan, yang berikut ini sudah cukup:

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

Ini mengambil anggota kedua dari tuple yang dikembalikan oleh isocalendar untuk nomor minggu kami.

Namun, jika Anda akan menggunakan fungsi tanggal yang berhubungan dengan kalender Gregorian, isocalendar saja tidak akan berfungsi! Ambil contoh berikut:

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

String di sini mengatakan untuk mengembalikan Senin dari minggu pertama tahun 2014 sebagai tanggal kami. Ketika kami menggunakan isocalendar untuk mengambil nomor minggu di sini, kami akan mengharapkan untuk mendapatkan nomor minggu yang sama kembali, tetapi kami tidak. Alih-alih kita mendapatkan angka 2 minggu. Mengapa?

Minggu 1 di kalender Gregorian adalah minggu pertama yang berisi hari Senin. Minggu 1 di isocalendar adalah minggu pertama yang berisi hari Kamis. Minggu parsial pada awal 2014 berisi Kamis, jadi ini adalah minggu 1 oleh kalender isocal, dan membuat dateminggu ke-2.

Jika kita ingin mendapatkan minggu Gregorian, kita perlu mengkonversi dari isocalendar ke Gregorian. Berikut adalah fungsi sederhana yang berfungsi.

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
sumber
6

Anda dapat mencoba arahan% W seperti di bawah ini:

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

'% W': Jumlah minggu dalam setahun (Senin sebagai hari pertama dalam seminggu) sebagai angka desimal. Semua hari dalam tahun baru sebelum Senin pertama dianggap dalam minggu ke-0 (00, 01, ..., 53)

Tung Nguyen
sumber
2

isocalendar () mengembalikan nilai tahun dan minggu kerja yang salah untuk beberapa tanggal:

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

Bandingkan dengan pendekatan 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
sumber
3
Melihat beberapa tautan tentang kalender iso8601 (mis. Staff.science.uu.nl/~gent0113/calendar/isocalendar.htm ), saya melihat bahwa nilai tahun dan angka minggu yang dikembalikan oleh isocalendar () tidak "salah". Di bawah ISO8601, misalnya, tahun 2004 dimulai pada 29 Desember 2003. Jadi isocalendar () mungkin benar dalam mengembalikan tahun 2015 untuk Dec.29 2014, tetapi untuk banyak tujuan orang, ini akan menjadi sangat menyesatkan .
Kevin
2

Saya meringkas diskusi menjadi dua langkah:

  1. Konversi format mentah ke datetimeobjek.
  2. Gunakan fungsi datetimeobjek atau dateobjek untuk menghitung angka minggu.

Pemanasan

`` `python

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

`` `

Langkah 1

Untuk menghasilkan datetimeobjek secara manual , kita dapat menggunakan datetime.datetime(2017,5,3)atau datetime.datetime.now().

Namun dalam kenyataannya, kita biasanya perlu mengurai string yang ada. kita dapat menggunakan strptimefungsi, seperti datetime.strptime('2017-5-3','%Y-%m-%d')di mana Anda harus menentukan format. Detail kode format yang berbeda dapat ditemukan di dokumentasi resmi .

Atau, cara yang lebih mudah adalah dengan menggunakan modul dateparse . Contohnya adalah dateparser.parse('16 Jun 2010'), dateparser.parse('12/2/12')ataudateparser.parse('2017-5-3')

Dua pendekatan di atas akan mengembalikan datetimeobjek.

Langkah ke-2

Gunakan datetimeobjek yang diperoleh untuk menelepon strptime(format). Sebagai contoh,

`` `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.

`` `

Sangat sulit untuk memutuskan format mana yang akan digunakan. Cara yang lebih baik adalah mendapatkan dateobjek untuk dipanggil isocalendar(). Sebagai contoh,

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

`` `

Pada kenyataannya, Anda akan lebih cenderung menggunakan date.isocalendar()untuk menyiapkan laporan mingguan, terutama di musim belanja "Natal-Tahun Baru".

Yuchao Jiang
sumber
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
sumber
-1

Banyak jawaban telah diberikan, tetapi saya ingin menambahkannya.

Jika Anda memerlukan minggu untuk ditampilkan sebagai gaya tahun / minggu (mis. 1953 - minggu 53 tahun 2019, 2001 - minggu 1 tahun 2020 dll.), Anda dapat melakukan ini:

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)

Dibutuhkan tahun dan minggu saat ini, dan long_week_num pada hari penulisan ini adalah:

>>> 2006
Simo Todorov
sumber
Mengapa membuat date()dari awal? datetime.datetime()contoh punya .date()metode untuk pekerjaan itu.
Martijn Pieters
Namun, yang lebih mengkhawatirkan adalah bahwa jawaban Anda memilih abad , bukan tahun ini. Dan jika Anda akan menggunakan pemformatan string untuk angka minggu, mengapa tidak menggunakan itu untuk memasukkan tahun?
Martijn Pieters