strftime

(PHP 3, PHP 4, PHP 5)

strftime -- 根据区域设置格式化本地时间/日期

说明

string strftime ( string format [, int timestamp] )

返回用给定的格式字串对给出的 timestamp 进行格式输出后的字符串。如果没有给出时间戳则用当前的本地时间。月份和星期几以及其它和语言有关的字符串写法和用 setlocale() 设定的当前的区域有关。

格式字串能识别下列转换标记:

  • %a - 当前区域星期几的简写

  • %A - 当前区域星期几的全称

  • %b - 当前区域月份的简写

  • %B - 当前区域月份的全称

  • %c - 当前区域首选的日期时间表达

  • %C - 世纪值(年份除以 100 后取整,范围从 00 到 99)

  • %d - 月份中的第几天,十进制数字(范围从 01 到 31)

  • %D - 和 %m/%d/%y 一样

  • %e - 月份中的第几天,十进制数字,一位的数字前会加上一个空格(范围从 ' 1' 到 '31')

  • %g - 和 %G 一样,但是没有世纪

  • %G - 4 位数的年份,符合 ISO 星期数(参见 %V)。和 %V 的格式和值一样,只除了如果 ISO 星期数属于前一年或者后一年,则使用那一年。

  • %h - 和 %b 一样

  • %H - 24 小时制的十进制小时数(范围从 00 到 23)

  • %I - 12 小时制的十进制小时数(范围从 00 到 12)

  • %j - 年份中的第几天,十进制数(范围从 001 到 366)

  • %m - 十进制月份(范围从 01 到 12)

  • %M - 十进制分钟数

  • %n - 换行符

  • %p - 根据给定的时间值为 `am' 或 `pm',或者当前区域设置中的相应字符串

  • %r - 用 a.m. 和 p.m. 符号的时间

  • %R - 24 小时符号的时间

  • %S - 十进制秒数

  • %t - 制表符

  • %T - 当前时间,和 %H:%M:%S 一样

  • %u - 星期几的十进制数表达 [1,7],1 表示星期一

    警告

    尽管 ISO 9889:1999(当前的 C 标准)明确指出一周从星期一开始,但是 Sun Solaris 的一周似乎从星期天开始并作为 1。

  • %U - 本年的第几周,从第一周的第一个星期天作为第一天开始

  • %V - 本年第几周的 ISO 8601:1988 格式,范围从 01 到 53,第 1 周是本年第一个至少还有 4 天的星期,星期一作为每周的第一天。(用 %G 或者 %g 作为指定时间戳相应周数的年份组成。)

  • %W - 本年的第几周数,从第一周的第一个星期一作为第一天开始

  • %w - 星期中的第几天,星期天为 0

  • %x - 当前区域首选的时间表示法,不包括时间

  • %X - 当前区域首选的时间表示法,不包括日期

  • %y - 没有世纪数的十进制年份(范围从 00 到 99)

  • %Y - 包括世纪数的十进制年份

  • %Z 或 %z - 时区名或缩写

  • %% - 文字上的 `%' 字符

注: 可能不是所有的转换标记都被 C 库文件支持,这种情况下 PHP 的 strftime() 也不支持。此外,不是所有的平台都支持负的时间戳,因此日期的范围可能限定在不早于 Unix 纪元。这意味着例如 %e, %T,%R 和 %D(可能更多)以及早于 Jan 1, 1970 的时间在 Windows,一些 Linux 发行版本,以及其它几个操作系统中无效。对于 Windows 系统,所支持的转换标记可在 MSDN 网站找到。

例子 1. strftime() 区域的例子

<?php
setlocale
(LC_TIME, "C");
echo
strftime("%A");
setlocale(LC_TIME, "fi_FI");
echo
strftime(" in Finnish is %A,");
setlocale(LC_TIME, "fr_FR");
echo
strftime(" in French %A and");
setlocale(LC_TIME, "de_DE");
echo
strftime(" in German %A.\n");
?>
本例在你的系统中安装有各自的区域设置后才能工作。

注: %G 和 %V,如果数字编号系统未能充分理解,基于 ISO 8601:1988 的星期数可能得出未预期的结果。见上面的 %V 和以下的例子。

例子 2. ISO 8601:1988 week number example

<?php
/*     December 2002 / January 2003
ISOWk  M   Tu  W   Thu F   Sa  Su
----- ----------------------------
51     16  17  18  19  20  21  22
52     23  24  25  26  27  28  29
1      30  31   1   2   3   4   5
2       6   7   8   9  10  11  12
3      13  14  15  16  17  18  19   */

// Outputs: 12/28/2002 - %V,%G,%Y = 52,2002,2002
echo "12/28/2002 - %V,%G,%Y = " . strftime("%V,%G,%Y", strtotime("12/28/2002")) . "\n";

// Outputs: 12/30/2002 - %V,%G,%Y = 1,2003,2002
echo "12/30/2002 - %V,%G,%Y = " . strftime("%V,%G,%Y", strtotime("12/30/2002")) . "\n";

// Outputs: 1/3/2003 - %V,%G,%Y = 1,2003,2003
echo "1/3/2003 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/3/2003")) . "\n";

// Outputs: 1/10/2003 - %V,%G,%Y = 2,2003,2003
echo "1/10/2003 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/10/2003")) . "\n";



/*     December 2004 / January 2005
ISOWk  M   Tu  W   Thu F   Sa  Su
----- ----------------------------
51     13  14  15  16  17  18  19
52     20  21  22  23  24  25  26
53     27  28  29  30  31   1   2
1       3   4   5   6   7   8   9
2      10  11  12  13  14  15  16   */

// Outputs: 12/23/2004 - %V,%G,%Y = 52,2004,2004
echo "12/23/2004 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("12/23/2004")) . "\n";

// Outputs: 12/31/2004 - %V,%G,%Y = 53,2004,2004
echo "12/31/2004 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("12/31/2004")) . "\n";

// Outputs: 1/2/2005 - %V,%G,%Y = 53,2004,2005
echo "1/2/2005 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/2/2005")) . "\n";

// Outputs: 1/3/2005 - %V,%G,%Y = 1,2005,2005
echo "1/3/2005 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/3/2005")) . "\n";

?>

参见 setlocale()mktime()strptime() 以及 Open Group specification of strftime()


add a note add a note User Contributed Notes
denis at spiralsolutions dot com
02-Nov-2006 04:07
(in addition to Andy's post)
To get a RFC 2822 date (used in RSS) of the current local time :

echo strftime ("%a, %d %b %Y %H:%M:%S %z") ;

Note: option %z / %Z - work different on Windows platform, for example
output of this code line can be:
Thu, 02 Nov 2006 09:54:59 Jerusalem Standard Time (on Windows)
Thu, 02 Nov 2006 09:54:59 +0200                  (on Linux)

[red. It is much smarter to use date(DATE_RSS); here]
NicSoft
07-Oct-2006 03:02
Marian Sigler
Your point about javascript not being universal is correct. However, accept language header does not tell you the local time difference, which is the essential problem.
Also, as you point out, accept language is also not universal.
Most browsers do accept javascript. it is in common use by many websites. It is a safe bet if you are using drop down menus for instance that the script will work, otherwise they would not be able to use your site at all.
Marian Sigler
19-Sep-2006 02:45
@NicSoft: And what if the user's browser doesn't support JavaScript? You should either use the possibilities offered by PHP (most browsers send an Accept-Language header, from where you can extract the language to use) or at least offer the english name (e.g. inside <noscript>)
NicSoft
22-Aug-2006 07:05
A simple work around for displaying dates in local format is to get the browser to do it for you using javascript.
This routine accepts a date time field from sql,
 and gets the timezone offset for your server, and passes these over to the browser in the form of a javascript script.
Javascript calculates the time difference and uses toLocaleString to display it.

function DisplaySQLDateInLocalTime($SQLDate){
list($year,$mon,$day,$hour,$min,$sec)=split('[-: ]',$SQLDate);
$TimeZoneOffset=date('Z') /60;
$JS="\n<script><!--\n";
$JS.="LocalTime = new Date();\n";
$JS.="TimeZoneOffsetInMins = LocalTime.getTimezoneOffset();\n";
$JS.="ServerTimeZoneOffset=$TimeZoneOffset;\n";
$JS.="timediff=-TimeZoneOffsetInMins - ServerTimeZoneOffset;\n";
$JS.="LocalTime = new Date(".$year.","
.($mon-1).",".$day.",".$hour.",".$min.",".$sec.");\n";
$JS.="DateVal=LocalTime.valueOf();\n";
$JS.="LocalTime=new Date(DateVal+timediff*1000*60);\n";
$JS.="document.write( LocalTime.toLocaleString());\n";
$JS.="//--></script>\n";
return $JS;
}
Moritz Stoltenburg
17-Aug-2006 11:45
In response to the note supplied by "Arpad Borsos":

I think the whole truth is that the output of strftime() considers whatever you stated with setlocale().

<?php

/* Berlin is in Germany */
$locale = setlocale (LC_ALL, 'de_DE.UTF-8');

/* Output: Donnerstag, 23. Mrz 2006 (and hopefully UTF-8 ;) */
echo strftime ("%A, %d. %B %Y", strtotime('2006-03-23'));

/* try different possible locale names for german as of PHP 4.3.0 */
$locale = setlocale(LC_ALL, 'de_DE.UTF-8', 'de_DE.UTF-8@euro', 'de_DE');
echo
"Preferred locale for german on this system is '$locale'";

?>

Check the documentation of setlocale() for more.
setlocale (LC_ALL, 'de_DE.UTF-8') always worked fine for me.
Arpad Borsos
17-Aug-2006 07:32
Please note that the strftime output is not encoded in utf8 so you have to use utf8_encode() if you want to print localized month names e.g. for German "Mrz"

[red. this depends on the platform though - some Windows locales *do* use UTF-8 for example]
reeveboy at hotmail dot com
28-Jul-2006 12:01
To mcallister, phloe and anyone else who want to get on the getDaySuffix() band wagon:

There are already functions to do this. All you really have to do is:

<?=date("jS", mktime(0,0,0,1,$myDay,2006))?>

Obviously, the only part of mktime that really matters is $myDay.
Moritz Stoltenburg
23-Jul-2006 01:54
In response to the note supplied by "segfault nycap rr com".

Here is a quicker and easier way:

Use the MySQL Time Function TIME_FORMAT() in your query:

mysql> SELECT TIME_FORMAT('14:35:00', '%l:%i %p');

Or try '%l' in PHP, it works on most systems and is part of the Open Group specification of strftime().

<?php

echo strftime('%l:%M %p', strtotime('14:35:00'));

?>
andy at yatescentral dot com
16-May-2006 11:47
When using strftime to generate time stamps for inclusion in  RSS feeds, be sure to use %z for the timezone (RFC-822 format) rather than %Z -- for some reason, %Z fails to validate.
posenato at sciNO dot univrSPAM dot it
15-May-2006 02:37
To partialy correct Neo's on RFC 850 date...

RFC 850 is obsolete by RFC 1036.

In HTTP header, RFC 1123 is the first choice: it has a fixed length format and 4 digits year.

Therefore, the correct format is:

gmstrftime ("%a, %d %b %Y %T %Z", time ());

Output example: Sun, 06 Nov 1994 08:49:37 GMT

[red. Use date(DATE_RFC850, time()); instead. (Or DATE_RFC1123 or DATE_RFC1036)]
Jon Keating
18-Jan-2006 09:49
Under windows if you are using Japanese version, you must use the following code:

setlocale(LC_ALL, "Japanese_Japan.20932") for EUC
setlocale(LC_ALL, "Japanese_Japan.932") for SJIS

I found the following page that helped me with this issue:
http://moodle.org/mod/forum/discuss.php?d=8329
php at REMOVEMEkennel17 dot co dot uk
20-Dec-2005 08:29
To correct an error in the above list of formatting codes:

%p - either `AM' or `PM' according to the given time value, or the corresponding strings for the current locale (note result is in capitals)
%P - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale (note result is in lower case)

In addition, the following codes seem to return a value on my system (Linux, Apache/1.3.33, PHP/4.4.1), but are not documented above.  I have included the result given by passing them to gmstrftime() with a timestamp of 0 (unix epoch).  gmstrftime() was used to avoid timezone/DST differences.

%F: "1970-01-01" (appears to be an SQL-formatted version of the date)
%k: "0" (seems to be the hour in 24-hour clock, without leading zeros (space-padded))
%l: "12" (seems to be the hour in 12-hour clock, without leading zeros (space-padded))
%s: "-3600"

%s seems to be the Unix timestamp passed to the function, but somehow based on the current locale/TZ settings (even in gmstrftime()). 
On my system strftime("%H:%M:%S", 0) returns "01:00:00", and strftime("%s", 0) returns "0".  Using gmstrftime() I get "00:00:00" and "-3600" respectively.
zackbloom at gmail dot com
07-Dec-2005 09:54
This function is useful for news posts.
It displays the creation date and elapsed time like:
Sunday, December 4, 2005 - 2 days ago
Monday, December 5, 2005 - Yesterday
Monday, November 28, 2005 - 1 week ago
Friday, October 28, 2005 - 6 weeks ago

function off($date){
$date = strtotime($date);
$offset = (strftime("%j")+strftime("%Y")*365)-
(strftime("%j",$date)+strftime("%Y",$date)*365);
if ($offset>7){
$offset = (strftime("%V")+strftime("%Y")*52)-
(strftime("%V",$date)+strftime("%Y",$date)*52);
$end=($offset!=0?($offset>1?$offset . " weeks ago":"a week ago"):"Today");
} else
$end=($offset!=0?($offset>1?"$offset days ago":"Yesterday"):"Today");
return strftime("%A, %B %e, %Y",$date)." - ". $end;
}

To insert the time:

<?=off("12/4/05")?>
jw at jwscripts dot com
29-May-2005 09:32
The following function implements the conversion specifiers which are not supported on Win32 platforms:

(Note: the specifiers %V, %G and %g can be implemented using other functions described in this section)

<?php

function strftime_win32($format, $ts = null) {
   if (!
$ts) $ts = time();

  
$mapping = array(
      
'%C' => sprintf("%02d", date("Y", $ts) / 100),
      
'%D' => '%m/%d/%y',
      
'%e' => sprintf("%' 2d", date("j", $ts)),
      
'%h' => '%b',
      
'%n' => "\n",
      
'%r' => date("h:i:s", $ts) . " %p",
      
'%R' => date("H:i", $ts),
      
'%t' => "\t",
      
'%T' => '%H:%M:%S',
      
'%u' => ($w = date("w", $ts)) ? $w : 7
  
);
  
$format = str_replace(
      
array_keys($mapping),
      
array_values($mapping),
      
$format
  
);

   return
strftime($format, $ts);
}

?>
patrick at codeministry dot dk
20-Apr-2005 05:50
For freebsd user:

You can find the full list of your locale under /usr/share/locale.
For example da_DK.ISO8859-1 under this directory will set up the locale to danish.
bohac at smartcat dot cz
20-Mar-2005 02:36
i had to use the czech representation of time on unix machine, running debian and linux version of apache with php 4

for me the best solution was to use this code:

<php
     setlocale(LC_ALL, 'cs_CZ.iso88592');
?>

then you can do everything in czech language with correct iso-8859-2 encoding ;D
Aaron
26-Jan-2005 05:10
%k will give you %H (hour, 24-hour clock) with the leading zero replaced by a space.  I have only tested this on one linux system so far, it may not work on windows or other linux builds.
michiel1978 at hotmail dot com
07-Oct-2004 05:31
As said in these comments, Windows strftime() doesn't support %e. However, to achieve a similar effect (not 100%) you can use %#d. The # flag will remove the leading zero, so you do get single digits, but without the space that would be added by %e in other environments.
neo at gothic-chat d0t de
25-Jun-2004 02:27
To get a RFC 850 date (used in HTTP) of the current time:

gmstrftime ("%A %d-%b-%y %T %Z", time ());

This will get for example:
Friday 25-Jun-04 03:30:23 GMT

Please note that times in HTTP-headers _must_ be GMT, so use gmstrftime() instead of strftime().
adan at cr72 dot com
10-Jun-2004 07:48
For Spanish:
<?
setlocale
(LC_ALL, "sp");
echo
strftime("%d. %B %Y");
?>
verhoeff
15-Apr-2004 06:54
The locale for dutch on a win2k computer is not "nl_NL"
but "dutch".
php_manual at it-rex dot nl
29-Mar-2004 09:31
In the strftime override-function of rickenmeer at hotmail dot com there is an error.

The line:
  $year = 1969;
should read:
  $year = 1970;
rolex
26-Mar-2004 12:37
Searching for translation from IBASE-Timestamp to EU-Dateformat DD.MM.YYYY

strftime("%d.%m.%Y",strtotime($row->START_TIMESTAMP));

Maybe it's useful for somebody ;-)
vminarik at ips-ag dot cz
10-Sep-2001 09:02
Note that setting LC_TIME is not enough for some locales under Windows, e.g. Czech, because there are some characters not contained in default (US) character set like '' (c with hook), '' (r with hook).


If you run Apache as regular application and have set your locale to Czech (ControlPanel/RegionalOptions), there is no problem and 'September' is correctly translated as 'z', 'Thursday' as 'tvrtek'.
But if you run Apache as service, you get 'zr', and 'ctvrtek'.
To get things work as you expect you must set LC_CTYPE beside LC_TIME, or set LC_ALL.

<?
  $locale
= 'Czech_Czech.1250';
 
$res = setlocale( 'LC_CTYPE', $locale); //important
 
$res = setlocale( 'LC_TIME', $locale);
  echo
strftime( '%A %m. %B %Y', mktime( 0,0,0,9,6,2001));
?>
verdy_p at wanadoo dot fr
22-Jul-2001 08:33
Beware of '%D':
the comment shown expects that this is the same as '%m/%d/%y'.

This is wrong: '%D' is only expected to returned an abbreviated numeric date according to the current locale:
In the German locale '%D' is '%y.%m.%d'
In the French locale '%D' is '%d/%m/%y'

The locale rules still apply to %D as with '%A'...

Beware that some C libraries do not support '%D' and/or '%A'  or do not support them accordingly. Using strftime() is then system-dependant, because PHP use the C function provided by the system on which it runs.
spamyenot at example dot com
19-Jul-2001 02:09
Solaris 2.6 and 7 define the
%u specifier differently than noted here. Day 1 is Sunday, not Monday. Solaris 8 gets it right.

Jim
zmajeed at cup dot hp dot com
23-Jul-1999 06:14
Locale names are OS dependent. HP-UX 11.0, for example, has three
German locales, de_DE.roman8, de_DE.iso88591, and
de_DE.iso885915@euro.
The command locale -a will display all available locales on a system.

So on HP-UX, to get German dates:
setlocale("LC_TIME", "de_DE.roman8");
print(strftime("%A\n"));