添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
霸气的小熊猫  ·  Stata | Features·  3 天前    · 
有腹肌的竹笋  ·  Changing String ...·  3 天前    · 
玩篮球的甘蔗  ·  Error Message: ...·  11 月前    · 
灰常酷的口罩  ·  带有Tomcat ...·  11 月前    · 
  • 如何获取用户归属地的时区信息
  • 如何设置时区信息
  • 我们先来看下为什么会有时区的概念。

    引入时区概念是因为地球绕着地轴自转,导致世界不同地区的日出日落时间不同。 为了以一致和标准化的方式记录时间,地球被划分为 24 个时区,每个时区的宽度约为经度 15 度。

    在引入时区之前,每个城市都有自己的本地时间,这是由太阳在天空中的位置决定的。 这导致了一个混乱和不一致的系统,火车和电报在不同的地方使用不同的时间,使得城市之间的交通和通讯难以协调。

    引入时区标准化计时,更容易协调交通和通信,减少混乱。 今天,时区是我们全球基础设施的重要组成部分,计算机、移动设备和其他系统使用时区以一致和标准化的方式跟踪时间。

    中国幅员辽阔,按国际通行时区划分标准可划分为东五区、东六区、东七区、东八区、东九区5个时区。民国时期全国时区被划分为昆仑时区、回藏时区(后改称新藏时区)、陇蜀时区、中原时区、以及长白时区。1949年中华人民共和国成立后,中国大陆全境统一划为东八区(UTC+8),同时以北京时间作为全国唯一的标准时间。

    除了中华人民共和国的大陆地区之外,香港与澳门也因地理位置以东八区做为标准时间,分别称作香港时间[1]与澳门标准时间[2]。1949年中华民国政府退守台湾后,全国时区仅剩中原时区,现今改称为国家标准时间、“台湾时间”或“台北时间”。

    美国由于东西跨度非常宽,共有六个标准时区:

  • 夏威夷标准时间 (HST)
  • 太平洋标准时间 (PST)
  • Mountain Standard Time (MST)
  • Central Standard Time (CST)
  • Eastern Standard Time (EST)
  • Atlantic Standard Time (AST)
  • 每个时区都有自己的标准时间,并且在美国的地图上呈现为一个圆形的区域。当地的标准时间是由当地的地理位置决定的,例如,夏威夷标准时间位于夏威夷群岛,而太平洋标准时间位于太平洋沿岸地区。

    1. 如何获取时区列表?

    服务器查看时区列表的方法

    我们以centos举例。时区信息存放路径为:/usr/share/zoneinfo。其他系统路径信息可以参考golang获取时区列表的方法。

    cd /usr/share/zoneinfo
    ls -a  #列举所有的时区信息。上海时区存在Asina目录下。
    

    我们根据路径信息就能拼接出时区,以shanghai举例。 shanghai时区文件存在 Asia目录中,我们进入Asia中,从文件中找到上海的文件“Shanghai”,这个时候时区值就是 “Asia/Shanghai” 。
    本地的时区信息,存放在 /etc/localtime中,其实这个文件就是一个链接,指向了/usr/share/zoneinfo目录下的一个文件。

    我们通过下面的命令,可以完成时区的设置信息。

    # Set timezone
    rm -rf /etc/localtime
    ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    

    Python中的获取时区列表的方法。

    我们可以借助python timezone模块,直接打印所有的时区即可。

    import pytz
    timezones = pytz.all_timezones
    print(timezones)
    

    Java中的获取时区列表的方法

    import java.util.TimeZone;
    public class TimeZoneList {
      public static void main(String[] args) {
        String[] availableIDs = TimeZone.getAvailableIDs();
        for (String id : availableIDs) {
          System.out.println(id);
    

    在此示例中,TimeZone.getAvailableIDs 方法用于获取所有可用时区 ID 的数组,然后使用 for-each 循环打印这些 ID。

    Golang中的获取方法

    golang的包并没有python,java齐全,时区列表的获取需要借助系统自带的时区信息。

    下面的代码从内容看,是读取服务器的目录信息,然后进行打印。通过路径信息可以看出,在windows,手机环境中就会存在问题。

    package main
    import (
        "fmt"
        "io/ioutil"
        "strings"
    var zoneDirs = []string{
        // Update path according to your OS
        "/usr/share/zoneinfo/",
        "/usr/share/lib/zoneinfo/",
        "/usr/lib/locale/TZ/",
    var zoneDir string
    func main() {
        for _, zoneDir = range zoneDirs {
            ReadFile("")
    func ReadFile(path string) {
        files, _ := ioutil.ReadDir(zoneDir + path)
        for _, f := range files {
            if f.Name() != strings.ToUpper(f.Name()[:1]) + f.Name()[1:] {
                continue
            if f.IsDir() {
                ReadFile(path + "/" + f.Name())
            } else {
                fmt.Println((path + "/" + f.Name())[1:])
    

    通过查询找到了另外一个版本,感觉这个版本应该是比较全的。其实后来想了想,其实手机应用中,应该很少使用golang写程序吧。

     package main
     import (
         "bytes"
         "fmt"
         "io/ioutil"
         "os/exec"
         "regexp/syntax"
         "runtime"
         "strings"
         "time"
         "unicode/utf8"
         // "golang.org/x/sys/windows/registry"
     // zoneDirs adapted from https://golang.org/src/time/zoneinfo_unix.go
     // https://golang.org/doc/install/source#environment
     // list of available GOOS as of 10th Feb 2017
     // android, darwin, dragonfly, freebsd, linux, netbsd, openbsd, plan9, solaris,windows
     var zoneDirs = map[string]string{
         "android":   "/system/usr/share/zoneinfo/",
         "darwin":    "/usr/share/zoneinfo/",
         "dragonfly": "/usr/share/zoneinfo/",
         "freebsd":   "/usr/share/zoneinfo/",
         "linux":     "/usr/share/zoneinfo/",
         "netbsd":    "/usr/share/zoneinfo/",
         "openbsd":   "/usr/share/zoneinfo/",
         // "plan9":"/adm/timezone/", -- no way to test this platform
         "solaris": "/usr/share/lib/zoneinfo/",
         "windows": `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`,
     var zoneDir string
     var timeZones []string
     // InSlice ... check if an element is inside a slice
     func InSlice(str string, list []string) bool {
         for _, v := range list {
             if v == str {
                 return true
         return false
     // ReadTZFile ... read timezone file and append into timeZones slice
     func ReadTZFile(path string) {
         files, _ := ioutil.ReadDir(zoneDir + path)
         for _, f := range files {
             if f.Name() != strings.ToUpper(f.Name()[:1])+f.Name()[1:] {
                 continue
             if f.IsDir() {
                 ReadTZFile(path + "/" + f.Name())
             } else {
                 tz := (path + "/" + f.Name())[1:]
                 // check if tz is already in timeZones slice
                 // append if not
                 if !InSlice(tz, timeZones) { // need a more efficient method...
                     // convert string to rune
                     tzRune, _ := utf8.DecodeRuneInString(tz[:1])
                     if syntax.IsWordChar(tzRune) { // filter out entry that does not start with A-Za-z such as +VERSION
                         timeZones = append(timeZones, tz)
     func ListTimeZones() {
         if runtime.GOOS == "nacl" || runtime.GOOS == "" {
             fmt.Println("Unsupported platform")
             os.Exit(0)
         // detect OS
         fmt.Println("Time zones available for : ", runtime.GOOS)
         fmt.Println("------------------------")
         fmt.Println("Retrieving time zones from : ", zoneDirs[runtime.GOOS])
         if runtime.GOOS != "windows" {
             for _, zoneDir = range zoneDirs {
                 ReadTZFile("")
         } else { // let's handle Windows
             // if you're building this on darwin/linux
             // chances are you will encounter
             // undefined: registry in registry.OpenKey error message
             // uncomment below if compiling on Windows platform
             //k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones`, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE)
             //if err != nil {
             // fmt.Println(err)
             //defer k.Close()
             //names, err := k.ReadSubKeyNames(-1)
             //if err != nil {
             // fmt.Println(err)
             //fmt.Println("Number of timezones : ", len(names))
             //for i := 0; i <= len(names)-1; i++ {
             // check if tz is already in timeZones slice
             // append if not
             // if !InSlice(names[i], timeZones) { // need a more efficient method...
             //  timeZones = append(timeZones, names[i])
             // UPDATE : Reading from registry is not reliable
             // better to parse output result by "tzutil /g" command
             // REMEMBER : There is no time difference between Coordinated Universal Time and Greenwich Mean Time ....
             cmd := exec.Command("tzutil", "/l")
             data, err := cmd.Output()
             if err != nil {
                 panic(err)
             fmt.Println("UTC is the same as GMT")
             fmt.Println("There is no time difference between Coordinated Universal Time and Greenwich Mean Time ....")
             GMTed := bytes.Replace(data, []byte("UTC"), []byte("GMT"), -1)
             fmt.Println(string(GMTed))
         now := time.Now()
         for _, v := range timeZones {
             if runtime.GOOS != "windows" {
                 location, err := time.LoadLocation(v)
                 if err != nil {
                     fmt.Println(err)
                 // extract the GMT
                 t := now.In(location)
                 t1 := fmt.Sprintf("%s", t.Format(time.RFC822Z))
                 tArray := strings.Fields(t1)
                 gmtTime := strings.Join(tArray[4:], "")
                 hours := gmtTime[0:3]
                 minutes := gmtTime[3:]
                 gmt := "GMT" + fmt.Sprintf("%s:%s", hours, minutes)
                 fmt.Println(gmt + " " + v)
             } else {
                 fmt.Println(v)
         fmt.Println("Total timezone ids : ", len(timeZones))
     func main() {
         ListTimeZones()
    

    php中获取时区列表的方法

    php不是非常的熟悉,只能写些简单的代码。通过代码分析,获取列表貌似只能参考时区官方文档

    github中开源时区列表

    github时区列表链接

    2. 如何设置时区?

    golang设置时区

    Go (Golang),可以使用time.FixedZone函数为一个time.Time值设置时区。

    package main
    import (
        "fmt"
        "time"
    func main() {
        location, err := time.LoadLocation("Asia/Shanghai")
        if err != nil {
            fmt.Println(err)
            return
        now := time.Now().In(location)
        fmt.Println("上海的时间是:", now)
    

    php设置时区

    在 PHP 中我们使用 date_default_timezone_set 函数为整个脚本设置时区。

    $timezone = new DateTimeZone('Asia/Shanghai');
    $date = new DateTime('now', $timezone);
    echo '现在的时间是: ' . $date->format('Y-m-d H:i:s');
    

    javascript或者nodejs中设置时区

    function get_local_time(timeZone) {
        let date = new Date();
        let formatter = new Intl.DateTimeFormat('zh-CN', {timeZone: timeZone, timeStyle: 'full', dateStyle: 'short'});
        return formatter.format(date)
    get_local_time("Asia/Shanghai");
    

    我们借助第三方js来实现设置时区的功能。

    var moment = require('moment-timezone');
    var timezone = 'Asia/Shanghai';
    var date = moment.tz(new Date(), timezone);
    console.log(date.format());
    

    请注意,需要先安装 moment-timezone 库,然后才能在项目中使用它。 可以通过在终端中运行以下命令来执行此操作:

    npm install moment-timezone
    

    moment-timezone官方文档参考链接

    java设置时区

    在 Java 中可以使用 TimeZone 类设置时区。 可以使用 getTimeZone 方法获取特定时区的 TimeZone 对象。在此示例中,使用 getTimeZone 方法获取“Asia/Shanghai”时区的 TimeZone 对象,然后使用 setDefault 方法将其设置为默认时区。

    import java.util.TimeZone;
    public class TimeZoneExample {
      public static void main(String[] args) {
        TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
        TimeZone.setDefault(tz);
    

    python设置时区

    import datetime
    import pytz
    timezone = pytz.timezone("America/Los_Angeles")
    date = datetime.datetime.now(timezone)
    print("Time in Los Angeles:", date)
    

    c设置时区

    #include 
    #include 
    #include 
    int main() {
      putenv("TZ=America/Los_Angeles");
      tzset();
      time_t rawtime;
      struct tm *timeinfo;
      time(&rawtime);
      timeinfo = localtime(&rawtime);
      printf("The current time in Los Angeles is: %s", asctime(timeinfo));
      return 0;
    

    在 C# 中,您可以使用 System 命名空间中的 TimeZone 类来设置时区。 TimeZone 类提供有关当前时区的信息,以及在不同时区之间转换的方法。

    下面是如何在 C# 中设置时区的示例:

    using System;
    class Program {
      static void Main(string[] args) {
        TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
        Console.WriteLine("The current time in Los Angeles is: " + TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz));
    

    在此示例中,FindSystemTimeZoneById 方法用于获取表示太平洋时区的 TimeZoneInfo 对象。 然后使用 ConvertTimeFromUtc 方法将当前 UTC 时间转换为太平洋时区的本地时间,并将结果打印到控制台。

    您可以通过调用 GetSystemTimeZones 方法找到支持的时区列表,该方法返回所有可用 TimeZoneInfo 对象的列表。 要为特定位置设置时区,您可以使用适当的时区标识符,例如太平洋时区的“Pacific Standard Time”.

    C++设置时区

    #include 
    #include 
    #include 
    int main() {
      setenv("TZ", "America/Los_Angeles", 1);
      tzset();
      time_t rawtime;
      struct tm *timeinfo;
      time(&rawtime);
      timeinfo = localtime(&rawtime);
      std::cout << "The current time in Los Angeles is: " << asctime(timeinfo);
      return 0;
    

    在此示例中,setenv 函数将 TZ 环境变量设置为 America/Los_Angeles,它指定了太平洋时区。 然后调用tzset函数读取TZ环境变量,为程序设置时区信息。

    time 函数用于获取当前时间作为 time_t 值,然后将其传递给 localtime 函数,将其转换为包含分解时间信息的 tm 结构,包括本地时区。 asctime 函数用于将细分的时间信息格式化为字符串,然后打印到控制台。

    大部分 Docker 镜像都是基于 Alpine,Ubuntu,Debian,CentOS 等镜像制作而成。这些镜像基本上都采用 UTC 时间,默认时区为零时区。如果创建web服务的时候,没有指定时区信息,后面会导致日志和统计信息等异常。下面是我常用的一种实现方式。

    #创建自己的网络
    docker network create --subnet=172.18.0.0/16 my-net
    # 我们使用 TZ(timezone的缩写)指定时区参数,使用--network指定ip。(如果docker中存在多个容器,服务重启的时候,你大概率会发现容器的ip变了。)--restart always docker启动的时候,自动启动容器 --volume指定空间。
    docker run -d  -e TZ="Asia/Shanghai" --network my-net --ip 172.18.0.2  --publish 6379:6379 --restart always --volume /data/redis:/data/redis --volume /data/redis/redis.conf:/etc/redis/redis.conf --name my-redis  redis redis-server /etc/redis/redis.conf
    

    服务器设置时区的方法

    使用Asia/Shanghai时区作为服务器的默认时区。

    # Set timezone
    rm -rf /etc/localtime
    ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    

    3. 参考链接

    1. 维基百科时区列表
    2. 时区列表参考
    3. 一个比较不错的时区列表,包含了主要的城市
    4. dockerfile创建镜像时指定时区
    5. dockerfile set timezone method
    6. 时区列表检索链接

    docker中创建容器时设置时区的方法

    C#设置时区