253 lines
5.5 KiB
Go
253 lines
5.5 KiB
Go
|
package utils
|
|||
|
|
|||
|
import (
|
|||
|
"reflect"
|
|||
|
"regexp"
|
|||
|
"strings"
|
|||
|
"net/http"
|
|||
|
"strconv"
|
|||
|
"time"
|
|||
|
"math"
|
|||
|
)
|
|||
|
|
|||
|
// IsIDCard 检查是否是身份证
|
|||
|
func IsIDCard(str string, args ...bool) bool {
|
|||
|
if m, _ := regexp.MatchString("^(?:[\\dxX]{15}|[\\dxX]{18})$", str); !m {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
areaMap := map[int]string{
|
|||
|
11 : "北京",
|
|||
|
12 : "天津",
|
|||
|
13 : "河北",
|
|||
|
14 : "山西",
|
|||
|
15 : "内蒙古",
|
|||
|
21 : "辽宁",
|
|||
|
22 : "吉林",
|
|||
|
23 : "黑龙江",
|
|||
|
31 : "上海",
|
|||
|
32 : "江苏",
|
|||
|
33 : "浙江",
|
|||
|
34 : "安徽",
|
|||
|
35 : "福建",
|
|||
|
36 : "江西",
|
|||
|
37 : "山东",
|
|||
|
41 : "河南",
|
|||
|
42 : "湖北",
|
|||
|
43 : "湖南",
|
|||
|
44 : "广东",
|
|||
|
45 : "广西",
|
|||
|
46 : "海南",
|
|||
|
50 : "重庆",
|
|||
|
51 : "四川",
|
|||
|
52 : "贵州",
|
|||
|
53 : "云南",
|
|||
|
54 : "西藏",
|
|||
|
61 : "陕西",
|
|||
|
62 : "甘肃",
|
|||
|
63 : "青海",
|
|||
|
64 : "宁夏",
|
|||
|
65 : "新疆",
|
|||
|
71 : "台湾",
|
|||
|
81 : "香港",
|
|||
|
82 : "澳门",
|
|||
|
91 : "国外",
|
|||
|
}
|
|||
|
|
|||
|
allowLen15 := true
|
|||
|
if len(args) == 1 {
|
|||
|
allowLen15 = args[0]
|
|||
|
}
|
|||
|
|
|||
|
province := Atoi(Substr(str, 0, 2))
|
|||
|
if _, ok := areaMap[province]; !ok {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
//如果是15位身份证
|
|||
|
if len(str) == 15 && allowLen15 {
|
|||
|
// 如果身份证顺序码是996 997 998 999,这些是为百岁以上老人的特殊编码
|
|||
|
code := Substr(str, 12, 3)
|
|||
|
if code == "996" || code == "997" || code == "998" || code == "999" {
|
|||
|
str = Substr(str, 0, 6) + "18" + Substr(str, 6, 9)
|
|||
|
} else {
|
|||
|
str = Substr(str, 0, 6) + "19" + Substr(str, 6, 9)
|
|||
|
}
|
|||
|
str += idcardVerifyNumber(str)
|
|||
|
}
|
|||
|
if len(str) != 18 || !checkIdcardFormat(str) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return idcardVerifyNumber(Substr(str, 0, 17)) == strings.ToUpper(Substr(str, 17, 1))
|
|||
|
}
|
|||
|
|
|||
|
// checkIdcardFormat 检查身份证号码的格式
|
|||
|
// 针对近期出现身份证号码使用210000000000000000注册的用户
|
|||
|
// 验证地区码(3-6位)以及生日(6-14)位
|
|||
|
func checkIdcardFormat(str string) bool {
|
|||
|
code := Atoi(Substr(str, 3, 3))
|
|||
|
if code == 0 {
|
|||
|
return false
|
|||
|
}
|
|||
|
if len(str) == 18 {
|
|||
|
birthYear := Atoi(Substr(str, 6, 4))
|
|||
|
birthMonth := Atoi(Substr(str, 10, 2))
|
|||
|
birthDay := Atoi(Substr(str, 10, 2))
|
|||
|
if birthYear < 1900 || (birthMonth == 0 || birthMonth > 12) || (birthDay == 0 || birthDay > 31) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// idcardVerifyNumber 计算身份证校验码,根据国家标准GB 11643-1999
|
|||
|
func idcardVerifyNumber(str string) string {
|
|||
|
if len(str) != 17 {
|
|||
|
return ""
|
|||
|
}
|
|||
|
|
|||
|
//加权因子
|
|||
|
factor := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
|||
|
//校验码对应值
|
|||
|
verifyNumberList := []string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}
|
|||
|
|
|||
|
checkSum := 0
|
|||
|
for i, l := 0, len(str); i < l; i++ {
|
|||
|
checkSum += Atoi(Substr(str, i, 1)) * factor[i]
|
|||
|
}
|
|||
|
checkSum = checkSum % 11
|
|||
|
return verifyNumberList[checkSum]
|
|||
|
}
|
|||
|
|
|||
|
// 是否为空
|
|||
|
func IsEmpty(val interface{}) (b bool) {
|
|||
|
defer func() {
|
|||
|
if err := recover(); err != nil {
|
|||
|
b = true
|
|||
|
}
|
|||
|
}()
|
|||
|
v := reflect.ValueOf(val)
|
|||
|
|
|||
|
switch v.Kind() {
|
|||
|
case reflect.Bool:
|
|||
|
b = (val.(bool) == false)
|
|||
|
case reflect.String:
|
|||
|
b = (val.(string) == "")
|
|||
|
case reflect.Array:
|
|||
|
fallthrough
|
|||
|
case reflect.Slice:
|
|||
|
fallthrough
|
|||
|
case reflect.Map:
|
|||
|
b = (v.Len() == 0)
|
|||
|
default:
|
|||
|
b = (v.Interface() == reflect.ValueOf(0).Interface() || v.Interface() == reflect.ValueOf(0.0).Interface())
|
|||
|
}
|
|||
|
|
|||
|
return b
|
|||
|
}
|
|||
|
|
|||
|
// 判断是否正确的ip地址
|
|||
|
func IsIp(ip string) bool {
|
|||
|
ips := strings.Split(ip, ".")
|
|||
|
if len(ips) != 4 {
|
|||
|
return false
|
|||
|
}
|
|||
|
for _, v := range ips {
|
|||
|
i := Atoi(v, -1)
|
|||
|
if i < 0 || i > 255 {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
//检测是否为手机设备
|
|||
|
func IsMobileDevice(r *http.Request) bool {
|
|||
|
agent := r.UserAgent()
|
|||
|
if strings.Contains(agent,"iPhone") || strings.Contains(agent,"iPad") || strings.Contains(agent,"iOS") || strings.Contains(agent,"Android") {
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// 检查字符串是否为纯数字组成
|
|||
|
func IsNumStr(s string) bool {
|
|||
|
if _, err := strconv.Atoi(s); err == nil {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// 检查字符串是否为纯数字组成
|
|||
|
func IsLongNumStr(s string) bool {
|
|||
|
if m, _ := regexp.MatchString("^\\d+$", s); m {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// IsMobileNum 检查是否是手机号
|
|||
|
func IsMobileNum(str string) bool {
|
|||
|
if m, _ := regexp.MatchString("^((13[\\d])|(147)|(15[\\d])|17[\\d]|(18[\\d]))[0-9]{8}$", str); m {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// IsVersionStr 检查字符串是否是一个版本格式
|
|||
|
func IsVersionStr(str string) bool {
|
|||
|
return IsVersion(str, "{2}")
|
|||
|
}
|
|||
|
|
|||
|
// IsVersion 检查字符串是否是一个版本格式
|
|||
|
func IsVersion(str string, length ...string) bool {
|
|||
|
vL := "{1,3}"
|
|||
|
if len(length) == 1 {
|
|||
|
vL = length[0]
|
|||
|
}
|
|||
|
if m, _ := regexp.MatchString("^\\d+(?:\\.\\d+)" + vL + "$", str); m {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// IsDeviceCode 检查字符串是否是一个机器码
|
|||
|
func IsDeviceCode(str string) bool {
|
|||
|
if m, _ := regexp.MatchString("^[a-zA-Z0-9]{40}$", str); m {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// RegexpOK 检查字符串被正则匹配
|
|||
|
func RegexpOK(pattern, str string) bool {
|
|||
|
if m, _ := regexp.MatchString(pattern, str); m {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// DiffDay 比较两个日志间隔的天数
|
|||
|
// 第1个日期小于第2个日期时返回正数
|
|||
|
// 第1个日期大于第2个日期时返回负数
|
|||
|
func DiffDay(t1, t2 string, fm ...string) (int, error) {
|
|||
|
format := "2006-01-02"
|
|||
|
if len(fm) == 1 {
|
|||
|
format = fm[0]
|
|||
|
}
|
|||
|
tm1, err := time.ParseInLocation(format, t1, time.Local)
|
|||
|
if err != nil {
|
|||
|
return 0, err
|
|||
|
}
|
|||
|
tm2, err := time.ParseInLocation(format, t2, time.Local)
|
|||
|
if err != nil {
|
|||
|
return 0, err
|
|||
|
}
|
|||
|
hour := tm2.Sub(tm1).Hours()
|
|||
|
if -24 >= hour || hour >= 24 {
|
|||
|
return int(math.Ceil(hour / 24)), nil
|
|||
|
}
|
|||
|
return 0, nil
|
|||
|
}
|