草庐IT

从 PHP 日期获取周数(年份)

codeneng 2023-03-28 原文

Get week number (in the year) from a date PHP

我想date并计算出它的周数。

到目前为止,我有以下内容。它应该是 42 时返回 24。

1
2
3
4
5
6
7
<?php
$ddate ="2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[2], $duedt[1],$duedt[0]);
$week = (int)date('W', $date);
echo"Weeknummer:".$week;
?>

数字颠倒是错误的巧合吗?还是我快到了?

  • 只是补充一下,不要忘记设置时区,使用 PHP.ini 或通过 date_default_timezone_set(\\'Asia/Singapore\\');
  • php.net/manual/en/function.date.php


今天,使用 PHP 的 DateTime 对象更好:

1
2
3
4
5
<?php
$ddate ="2012-10-18";
$date = new DateTime($ddate);
$week = $date->format("W");
echo"Weeknummer: $week";

这是因为在mktime()中,它是这样的:

1
mktime(hour, minute, second, month, day, year);

因此,您的订单是错误的。

1
2
3
4
5
6
7
<?php
$ddate ="2012-10-18";
$duedt = explode("-", $ddate);
$date  = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
$week  = (int)date('W', $date);
echo"Weeknummer:" . $week;
?>

  • 您可以使用 Carbon,"github.com/briannesbitt/Carbon"来最大化您在日期操作方面的技能。对于碳,你可以这样做:Carbon::createFromFormat('Y-m-d H', '2012-10-18')->format('W');
  • 实际上,最好只使用 PHP 的原生 DateTime 对象。
  • @lukaserat这与接受的答案使用的有什么不同(除了OP必须包含对语言中已经是原生的东西的外部依赖之外)?
  • @PeeHaa 很多时候我不想干我的代码,如果已经有好的代码。
  • 我会说 mktime() 中的顺序是错误的,而不是 OP 的顺序。当然,后者更容易改变。
  • @beetstra 我想说的是,在 2014 年的今天,如果你使用 mktime() 而不是 new DateTime,那肯定是你错了 :)
  • 正如 fedmich 还建议的那样,将 new DateTime($date, new DateTimeZone('Europe/Amsterdam')); 用于您自己的时区:)
  • Yesssss,它的工作......完美的计算。谢谢@Madara Uchiha。
  • 如果 12 月的最后一周也是明年的第一周(如 2019 年),那么您将获得周数为 1,对于该周内的日期(如 30、31)
  • @Shah Abaz Khan 在需要年份信息的情况下,可以使用 strftime()。我已经添加它作为这个问题的答案。


1
2
$date_string ="2012-10-18";
echo"Weeknummer:" . date("W", strtotime($date_string));

使用 PHP 的日期函数
http://php.net/manual/en/function.date.php

1
date("W", $yourdate)

  • 这不起作用,您必须改为 date("W", strtotime($yourdate))


这得到今天的日期,然后告诉一周的周数

1
2
3
4
<?php
 $date=date("W");
 echo $date." Week Number";
 ?>

作为一个建议:

1
<?php echo date("W", strtotime("2012-10-18")); ?>

可能比所有这些都简单一点。

你可以做的其他事情:

1
2
<?php echo date("Weeknumber: W", strtotime("2012-10-18 01:00:00")); ?>
<?php echo date("Weeknumber: W", strtotime($MY_DATE)); ?>

我多年来一直试图解决这个问题,我以为我找到了一个更短的解决方案,但不得不再次回到长篇大论。此函数返回正确的 ISO 周符号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
 * calcweek("2018-12-31") => 1901
 * This function calculates the production weeknumber according to the start on
 * monday and with at least 4 days in the new year. Given that the $date has
 * the following format Y-m-d then the outcome is and integer.
 *
 * @author M.S.B. Bachus
 *
 * @param date-notation PHP"Y-m-d" showing the data as yyyy-mm-dd
 * @return integer
 **/

function calcweek($date) {
  // 1. Convert input to $year, $month, $day
  $dateset      = strtotime($date);
  $year         = date("Y", $dateset);
  $month        = date("m", $dateset);
  $day          = date("d", $dateset);

  $referenceday = getdate(mktime(0,0,0, $month, $day, $year));
  $jan1day      = getdate(mktime(0,0,0,1,1,$referenceday[year]));

  // 2. check if $year is a  leapyear
  if ( ($year%4==0 && $year%100!=0) || $year%400==0) {
    $leapyear = true;
  } else {
    $leapyear = false;
  }

  // 3. check if $year-1 is a  leapyear
  if ( (($year-1)%4==0 && ($year-1)%100!=0) || ($year-1)%400==0 ) {
    $leapyearprev = true;
  } else {
    $leapyearprev = false;
  }

  // 4. find the dayofyearnumber for y m d
  $mnth = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
  $dayofyearnumber = $day + $mnth[$month-1];
  if ( $leapyear && $month > 2 ) { $dayofyearnumber++; }

  // 5. find the jan1weekday for y (monday=1, sunday=7)
  $yy = ($year-1)%100;
  $c  = ($year-1) - $yy;
  $g  = $yy + intval($yy/4);
  $jan1weekday = 1+((((intval($c/100)%4)*5)+$g)%7);

  // 6. find the weekday for y m d
  $h = $dayofyearnumber + ($jan1weekday-1);
  $weekday = 1+(($h-1)%7);

  // 7. find if y m d falls in yearnumber y-1, weeknumber 52 or 53
  $foundweeknum = false;
  if ( $dayofyearnumber <= (8-$jan1weekday) && $jan1weekday > 4 ) {
    $yearnumber = $year - 1;
    if ( $jan1weekday = 5 || ( $jan1weekday = 6 && $leapyearprev )) {
      $weeknumber = 53;
    } else {
      $weeknumber = 52;
    }
    $foundweeknum = true;
  } else {
    $yearnumber = $year;
  }

  // 8. find if y m d falls in yearnumber y+1, weeknumber 1
  if ( $yearnumber == $year && !$foundweeknum) {
    if ( $leapyear ) {
      $i = 366;
    } else {
      $i = 365;
    }
    if ( ($i - $dayofyearnumber) < (4 - $weekday) ) {
      $yearnumber = $year + 1;
      $weeknumber = 1;
      $foundweeknum = true;
    }
  }

  // 9. find if y m d falls in yearnumber y, weeknumber 1 through 53
  if ( $yearnumber == $year && !$foundweeknum ) {
    $j = $dayofyearnumber + (7 - $weekday) + ($jan1weekday - 1);
    $weeknumber = intval( $j/7 );
    if ( $jan1weekday > 4 ) { $weeknumber--; }
  }

  // 10. output iso week number (YYWW)
  return ($yearnumber-2000)*100+$weeknumber;
}

我发现我的简短解决方案错过了 2018-12-31,因为它返回的是 1801 而不是 1901。所以我不得不输入这个正确的长版本。


当您需要年和周时变得更加困难。
尝试找出哪一周是 01.01.2017。
(这是 2016 年的第 52 周,即从 Mon 26.12.2016 - Sun 01.01.2017)。

经过长时间的搜索,我找到了

1
strftime('%G-%V',strtotime("2017-01-01"))

结果:2016-52

https://www.php.net/manual/de/function.strftime.php
ISO-8601:1988 给定年份的周数,从一年的第一周开始,至少有 4 个工作日,星期一是一周的开始。 (01 到 53)

mysql中的等价物是DATE_FORMAT(date, '%x-%v')
https://www.w3schools.com/sql/func_mysql_date_format.asp
星期一是一周的第一天的星期(01 到 53)。

找不到使用 date() 或 DateTime 的相应解决方案。
至少不是没有像"1day, last monday"这样的解决方案。

  • 这是一个适合年和周的巧妙解决方案,但不幸的是 strftime() 自 PHP 8.1.0 起已弃用 php.net/manual/en/function.strftime.php


使用 IntlGregorianCalendar 类怎么样?

要求:在开始使用 IntlGregorianCalendar 之前,请确保在服务器上安装了 libicupecl/intl
所以在 CLI 上运行:

1
php -m

如果您在 [PHP Modules] 列表中看到 intl,那么您可以使用 IntlGregorianCalendar.

DateTime 与 IntlGregorianCalendar:
IntlGregorianCalendar 并不比 DateTime 好。但是 IntlGregorianCalendar 的好处是它会以 int 的形式为您提供周数。

示例:

1
2
3
4
5
$dateTime = new DateTime('21-09-2020 09:00:00');
echo $dateTime->format("W"); // string '39'

$intlCalendar = IntlCalendar::fromDateTime ('21-09-2020 09:00:00');
echo $intlCalendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR); // integer 39

当一年有 53 周(如 2020 年)时,上面给出的大多数示例都会产生问题。所以每四年你会经历一周的差异。此代码没有:

1
2
3
4
5
6
7
8
9
10
11
12
$thisYear ="2020";
$thisDate ="2020-04-24"; //or any other custom date
$weeknr = date("W", strtotime($thisDate)); //when you want the weeknumber of a specific week, or just enter the weeknumber yourself

$tempDatum = new DateTime();
$tempDatum->setISODate($thisYear, $weeknr);
$tempDatum_start = $tempDatum->format('Y-m-d');
$tempDatum->setISODate($thisYear, $weeknr, 7);
$tempDatum_end = $tempDatum->format('Y-m-d');

echo $tempDatum_start //will output the date of monday
echo $tempDatum_end // will output the date of sunday

1
2
3
4
5
6
7
<?php
$ddate ="2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[1], $duedt[2],$duedt[0]);
$week = (int)date('W', $date);
echo"Weeknummer:".$week;
?>

您的 mktime 参数错误 - 需要是月/日/年,而不是日/月/年


要获取北美日期的星期数,我这样做:

1
2
3
4
5
6
7
8
9
function week_number($n)
{
    $w = date('w', $n);
    return 1 + date('z', $n + (6 - $w) * 24 * 3600) / 7;
}

$n = strtotime('2022-12-27');
printf("%s: %d\
"
, date('D Y-m-d', $n), week_number($n));

并得到:

Tue 2022-12-27: 53


规则是一年的第一周是包含一年中第一个星期四的那一周。

我个人使用 Zend_Date 来进行这种计算,获取今天的星期就这么简单。如果您使用日期,它们还有许多其他有用的功能。

1
2
3
$now = Zend_Date::now();
$week = $now->get(Zend_Date::WEEK);
// 10

  • 这是一条规则(部分来自 ISO 8601)。这就是 php 的 date('W', $date) 所基于的。不过,这不是唯一的规则。
  • 我有不同的年份数据,是否可以使用 date('W', $date)


很简单
只有一行:

1
<?php $date=date("W"); echo"Week" . $date; ?>"

你也可以,例如我需要一个图表,减去前一周,如:

1
<?php $date=date("W"); echo"Week" . ($date - 1); ?>

要获得日期 2018-12-31 的正确周数,请使用以下代码

1
2
3
4
5
6
7
8
9
$day_count = date('N',strtotime('2018-12-31'));
$week_count = date('W',strtotime('2018-12-31'));    


if($week_count=='01' && date('m',strtotime('2018-12-31'))==12){
    $yr_count = date('y',strtotime('2018-12-31')) + 1;
}else{
    $yr_count = date('y',strtotime('2018-12-31'));
}

要获取 jalai 日历中的周数,您可以使用:

1
2
3
4
5
6
7
8
9
10
$weeknumber = date("W"); //number week in year
$dayweek = date("w"); //number day in week
if ($dayweek =="6")
{
    $weeknumberint = (int)$weeknumber;
    $date2int++;
    $weeknumber = (string)$date2int;
}

echo $date2;

结果:

1
15

周六周数变化

  • 欢迎来到 stackoverflow.com。有趣的一点是,不同日历中的周数变化不同。但是,请为您的代码使用 DateTime 对象。此外,您没有在使用它们之前声明变量。它在 PHP 中是允许的,但不是最佳实践。不管怎样,谢谢你的第一次贡献。


您的代码可以运行,但您需要翻转第 4 和第 5 个参数。

我会这样做

1
2
3
4
5
$date_string ="2012-10-18";
$date_int = strtotime($date_string);
$date_date = date($date_int);
$week_number = date('W', $date_date);
echo"Weeknumber: {$week_number}.";

另外,一周不看代码后,你的变量名会让你感到困惑,你应该考虑阅读 http://net.tutsplus.com/tutorials/php/why-youre-a-bad-php -程序员/


试试这个解决方案

1
date( 'W', strtotime("2017-01-01 + 1 day" ) );

  • 2017-01-01 是星期天。添加一天会让您进入下一周,从星期一开始几周。 2017-01-01 是 2016 年的第 52 周。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function last_monday($date)
{
    if (!is_numeric($date))
        $date = strtotime($date);
    if (date('w', $date) == 1)
        return $date;
    else
        return date('Y-m-d',strtotime('last monday',$date));
}
$date = '2021-01-04';  //Enter custom date
$year = date('Y',strtotime($date));
$date1 = new DateTime($date);
$ldate = last_monday($year."-01-01");
$date2 = new DateTime($ldate);
$diff = $date2->diff($date1)->format("%a");
$diff = $diff/7;
$week = intval($diff) + 1;
echo $week;
//Returns 2.

有关从 PHP 日期获取周数(年份)的更多相关文章

  1. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  2. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  3. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  4. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

  5. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  6. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  7. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  8. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  9. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  10. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

随机推荐