• 时区的问题


    不同系统的失去配置文件不同 以 centos为例

    配置文件

    /etc/localtime  -> /usr/share/zoneinfo/...
    
    $ ls /etc/localtime  -lh
    /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai
    
    $ date -R
    Fri, 12 Aug 2022 17:59:11 +0800
    
    表示东八区
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    dockerfile 中设置时区

    
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    
    
    • 1
    • 2
    • 3
    • 4

    gorm 使用时区

    • 连接串dsn中可以指定loc dsn := "admin:admin@tcp(192.168.156.100:3306)/gorm?charset=utf8&parseTime=True&loc=Local"
      从数据库中读出的时间的字符串,指定parseTime就将字符串解析成time格式
    /Users/zhangqian458/.gopath/src/github.com/go-sql-driver/mysql/packets.go
    readRow() {
    if !mc.parseTime {
      continue
        } else {
    					switch rows.rs.columns[i].fieldType {
    					case fieldTypeTimestamp, fieldTypeDateTime,
    						fieldTypeDate, fieldTypeNewDate:
      dest[i], err = parseDateTime(
    							string(dest[i].([]byte)),
    							mc.cfg.Loc,
    						)
    if err == nil {
      continue
        }
    default:
    continue
      }
    				}
    }
        
    /src/github.com/go-sql-driver/mysql/utils.go
    func parseDateTime(str string, loc *time.Location) (t time.Time, err error) {
    	base := "0000-00-00 00:00:00.0000000"
    	switch len(str) {
    	case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM"
    if str == base[:len(str)] {
      return
        }
    		t, err = time.Parse(timeFormat[:len(str)], str)
    default:
      err = fmt.Errorf("invalid time string: %s", str)
    return
      }
    
    	// Adjust location
    if err == nil && loc != time.UTC {
    		y, mo, d := t.Date()
    		h, mi, s := t.Clock()
    		t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil
    	}
    
      return
        }
    
    • 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

    不指定就会使用默认的,默认的也就是local

    上边中:
    		t, err = time.Parse(timeFormat[:len(str)], str)
    
    func Parse(layout, value string) (Time, error) {
    	return parse(layout, value, UTC, Local)
    }
    // Local represents the system's local time zone.
    // On Unix systems, Local consults the TZ environment
    // variable to find the time zone to use. No TZ means
    // use the system default /etc/localtime.
    // TZ="" means use UTC.
    // TZ="foo" means use file foo in the system timezone directory.
    var Local *Location = &localLoc
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    source code

    
    package main
    
    import (
      "encoding/json"
      "time"
    
      "github.com/zssky/log"
      "gorm.io/driver/mysql"
      "gorm.io/gorm"
    )
    
    type TimeModel struct {
    	T *time.Time `gorm:default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;comment:'修改时间''"`
    }
    
    func (*TimeModel) TableName() string {
    	return "vvv"
    }
    
    func dbInit() (*gorm.DB, error) {
    
    	dsn := "admin:admin@tcp(192.168.156.100:3306)/gorm?charset=utf8&parseTime=True&loc=Local"
    	return gorm.Open(mysql.New(mysql.Config{
    		DSN:                       dsn,   // DSN data source name
    		DefaultStringSize:         256,   // string 类型字段的默认长度
    		DisableDatetimePrecision:  true,  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
    		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
    		DontSupportRenameColumn:   true,  // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
    		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
    	}), &gorm.Config{})
    
    }
    
    func main() {
    	db, err := dbInit()
    	if err != nil {
    		log.Error(err)
    		return
    	}
    	r := TimeModel{}
    
    	if err = db.Model(&TimeModel{}).First(&r).Error; err != nil {
    		log.Error(err)
    		return
    	}
    	o, e := json.Marshal(r)
    	if e != nil {
    		log.Error(err)
    		return
    	}
    	log.Infof("%#v", *r.T)
    	log.Info(string(o))
    }
    
    
    • 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

    时区信息在第一次使用时间是加载

    go/src/time/zoneinfo_unix.go
    
    func (l *Location) get() *Location {
    if l == nil {
      return &utcLoc
    	}
    if l == &localLoc {
    		localOnce.Do(initLocal)
    	}
      return l
        }
    
    // Many systems use /usr/share/zoneinfo, Solaris 2 has
    // /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
    var zoneSources = []string{
    	"/usr/share/zoneinfo/",
    	"/usr/share/lib/zoneinfo/",
    	"/usr/lib/locale/TZ/",
    	runtime.GOROOT() + "/lib/time/zoneinfo.zip",
    }
    
    func initLocal() {
    	// consult $TZ to find the time zone to use.
    	// no $TZ means use the system default /etc/localtime.
    	// $TZ="" means use UTC.
    	// $TZ="foo" or $TZ=":foo" if foo is an absolute path, then the file pointed
    	// by foo will be used to initialize timezone; otherwise, file
    	// /usr/share/zoneinfo/foo will be used.
    
    	tz, ok := syscall.Getenv("TZ")
    	switch {
    	case !ok:
    		z, err := loadLocation("localtime", []string{"/etc"})
    		if err == nil {
    			localLoc = *z
    			localLoc.name = "Local"
    			return
    		}
    	case tz != "":
    		if tz[0] == ':' {
    			tz = tz[1:]
    		}
    		if tz != "" && tz[0] == '/' {
    			if z, err := loadLocation(tz, []string{""}); err == nil {
    				localLoc = *z
    				if tz == "/etc/localtime" {
    					localLoc.name = "Local"
    				} else {
    					localLoc.name = tz
    				}
    				return
    			}
    		} else if tz != "" && tz != "UTC" {
    			if z, err := loadLocation(tz, zoneSources); err == nil {
    				localLoc = *z
    				return
    			}
    		}
    	}
    
    	// Fall back to UTC.
    	localLoc.name = "UTC"
    }
    
    • 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

    系统调用

    rt_sigaction(SIGRT_32, {sa_handler=0x463fe0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x464120}, NULL, 8) = 0
    rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
    clone(child_stack=0xc00008e000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc00007e090) = 245
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    --- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=244, si_uid=0} ---
    rt_sigreturn({mask=[]})                 = 0
    --- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=244, si_uid=0} ---
    rt_sigreturn({mask=[]})                 = 0
    --- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=244, si_uid=0} ---
    rt_sigreturn({mask=[]})                 = 10322680
    rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
    clone(child_stack=0xc000090000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc00007e490) = 246
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    futex(0xc00007e548, FUTEX_WAKE_PRIVATE, 1) = 1
    rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
    clone(child_stack=0xc00008a000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc00007e890) = 248
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    fcntl(0, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
    futex(0xc00007e948, FUTEX_WAKE_PRIVATE, 1) = 1
    fcntl(1, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
    fcntl(2, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
    openat(AT_FDCWD, "/usr/share/zoneinfo//Asia/Shanghai", O_RDONLY) = 3
    read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\2\0\0\0\0"..., 4096) = 556
    read(3, "", 4096)                       = 0
    close(3)                                = 0
    write(1, "2022/08/12 18:42:12 main.go:34: "..., 692022/08/12 18:42:12 main.go:34: info 0 "hello you see me"
    ) = 69
    write(1, "2022/08/12 18:42:12 main.go:38: "..., 712022/08/12 18:42:12 main.go:38: info main "ttttttttttttttt"
    ) = 71
    futex(0xc000100148, FUTEX_WAKE_PRIVATE, 1) = 1
    socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3
    connect(3, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("192.168.156.100")}, 16) = -1 EINPROGRESS (Operation now in progress)
    epoll_create1(EPOLL_CLOEXEC)            = 4
    pipe2([5, 6], O_NONBLOCK|O_CLOEXEC)     = 0
    epoll_ctl(4, EPOLL_CTL_ADD, 5, {EPOLLIN, {u32=10511816, u64=10511816}}) = 0
    epoll_ctl(4, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=2261080856, u64=140525001071384}}) = 0
    epoll_pwait(4, [], 128, 0, NULL, 2)     = 0
    epoll_pwait(4, [{EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=2261080856, u64=140525001071384}}], 128, -1, NULL, 0) = 1
    futex(0x9d83d8, FUTEX_WAKE_PRIVATE, 1)  = 1
    futex(0x9d82f8, FUTEX_WAKE_PRIVATE, 1)  = 1
    getsockopt(3, SOL_SOCKET, SO_ERROR, [110], [4]) = 0
    epoll_ctl(4, EPOLL_CTL_DEL, 3, 0xc00015b04c) = 0
    close(3)                                = 0
    write(1, "\r\n2022/08/12 18:42:27 \33[35m/User"..., 219
    2022/08/12 18:42:27 /Users/zhangqian458/git-jd/src/git.jd.com/drc/mytest/time/main.go:23
    [error] failed to initialize database, got error dial tcp 192.168.156.100:3306: connect: connection timed out
    ) = 219
    write(1, "2022/08/12 18:42:27 main.go:41: "..., 1172022/08/12 18:42:27 main.go:41: error main  dial tcp 192.168.156.100:3306: connect: connection timed out
    ) = 117
    exit_group(0)                           = ?
    +++ exited with 0 +++
    
    • 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

    data 命令的系统调用

    execve("/usr/bin/date", ["date"], [/* 22 vars */]) = 0
    brk(NULL)                               = 0x1f63000
        
    ...
        
    open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=103860, ...}) = 0
    mmap(NULL, 103860, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff61912e000
    close(3)                                = 0
    open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
    fcntl(3, F_GETFD)                       = 0x1 (flags FD_CLOEXEC)
    fstat(3, {st_mode=S_IFREG|0644, st_size=2492, ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff61914e000
    read(3, "# Locale name alias data base.\n#"..., 4096) = 2492
    read(3, "", 4096)                       = 0
    close(3)                                = 0
    munmap(0x7ff61914e000, 4096)            = 0
        
    ...
        
    open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=388, ...}) = 0
    fstat(3, {st_mode=S_IFREG|0644, st_size=388, ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff61914e000
    read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\2\0\0\0\0"..., 4096) = 388
    lseek(3, -240, SEEK_CUR)                = 148
    read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\0"..., 4096) = 240
    close(3)                                = 0
    munmap(0x7ff61914e000, 4096)            = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff61914e000
    write(1, "Fri Aug 12 18:00:25 CST 2022\n", 29Fri Aug 12 18:00:25 CST 2022
    ) = 29
    close(1)                                = 0
    munmap(0x7ff61914e000, 4096)            = 0
    close(2)                                = 0
    
    
    • 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
  • 相关阅读:
    StreamBuilder 用法示例
    基于EKF扩展卡尔曼滤波的传感器网络目标跟踪matlab仿真
    4月24日,每日信息差
    视频拍摄教程分享
    leetcode 13. 罗马数字转整数
    一个工地狗变成程序猿的故事
    linux下搭建oh-my-zsh环境
    Nginx配置SSL证书
    【动画进阶】当路径动画遇到滚动驱动!
    【动手学深度学习】--长短期记忆网络LSTM
  • 原文地址:https://blog.csdn.net/bigjordon/article/details/126310109