mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 12:11:28 +00:00
added functionality for column type time
updated the model_fields to cater for the time field type
This commit is contained in:
parent
ebdf4412b3
commit
d49c7f96cb
@ -55,6 +55,8 @@ checkColumn:
|
|||||||
col = fmt.Sprintf(T["string"], fieldSize)
|
col = fmt.Sprintf(T["string"], fieldSize)
|
||||||
case TypeTextField:
|
case TypeTextField:
|
||||||
col = T["string-text"]
|
col = T["string-text"]
|
||||||
|
case TypeTimeField:
|
||||||
|
col = T["time.Time-clock"]
|
||||||
case TypeDateField:
|
case TypeDateField:
|
||||||
col = T["time.Time-date"]
|
col = T["time.Time-date"]
|
||||||
case TypeDateTimeField:
|
case TypeDateTimeField:
|
||||||
@ -264,7 +266,7 @@ func getColumnDefault(fi *fieldInfo) string {
|
|||||||
|
|
||||||
// These defaults will be useful if there no config value orm:"default" and NOT NULL is on
|
// These defaults will be useful if there no config value orm:"default" and NOT NULL is on
|
||||||
switch fi.fieldType {
|
switch fi.fieldType {
|
||||||
case TypeDateField, TypeDateTimeField, TypeTextField:
|
case TypeTimeField, TypeDateField, TypeDateTimeField, TypeTextField:
|
||||||
return v
|
return v
|
||||||
|
|
||||||
case TypeBitField, TypeSmallIntegerField, TypeIntegerField,
|
case TypeBitField, TypeSmallIntegerField, TypeIntegerField,
|
||||||
|
18
orm/db.go
18
orm/db.go
@ -24,6 +24,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
formatTime = "15:04:05"
|
||||||
formatDate = "2006-01-02"
|
formatDate = "2006-01-02"
|
||||||
formatDateTime = "2006-01-02 15:04:05"
|
formatDateTime = "2006-01-02 15:04:05"
|
||||||
)
|
)
|
||||||
@ -175,7 +176,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
|
|||||||
value = field.Float()
|
value = field.Float()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case TypeDateField, TypeDateTimeField:
|
case TypeTimeField, TypeDateField, TypeDateTimeField:
|
||||||
value = field.Interface()
|
value = field.Interface()
|
||||||
if t, ok := value.(time.Time); ok {
|
if t, ok := value.(time.Time); ok {
|
||||||
d.ins.TimeToDB(&t, tz)
|
d.ins.TimeToDB(&t, tz)
|
||||||
@ -229,7 +230,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch fi.fieldType {
|
switch fi.fieldType {
|
||||||
case TypeDateField, TypeDateTimeField:
|
case TypeTimeField, TypeDateField, TypeDateTimeField:
|
||||||
if fi.autoNow || fi.autoNowAdd && insert {
|
if fi.autoNow || fi.autoNowAdd && insert {
|
||||||
if insert {
|
if insert {
|
||||||
if t, ok := value.(time.Time); ok && !t.IsZero() {
|
if t, ok := value.(time.Time); ok && !t.IsZero() {
|
||||||
@ -1098,7 +1099,7 @@ setValue:
|
|||||||
} else {
|
} else {
|
||||||
value = str.String()
|
value = str.String()
|
||||||
}
|
}
|
||||||
case fieldType == TypeDateField || fieldType == TypeDateTimeField:
|
case fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField:
|
||||||
if str == nil {
|
if str == nil {
|
||||||
switch t := val.(type) {
|
switch t := val.(type) {
|
||||||
case time.Time:
|
case time.Time:
|
||||||
@ -1118,15 +1119,20 @@ setValue:
|
|||||||
if len(s) >= 19 {
|
if len(s) >= 19 {
|
||||||
s = s[:19]
|
s = s[:19]
|
||||||
t, err = time.ParseInLocation(formatDateTime, s, tz)
|
t, err = time.ParseInLocation(formatDateTime, s, tz)
|
||||||
} else {
|
} else if len(s) >= 10 {
|
||||||
if len(s) > 10 {
|
if len(s) > 10 {
|
||||||
s = s[:10]
|
s = s[:10]
|
||||||
}
|
}
|
||||||
t, err = time.ParseInLocation(formatDate, s, tz)
|
t, err = time.ParseInLocation(formatDate, s, tz)
|
||||||
|
} else if len(s) >= 8 {
|
||||||
|
if len(s) > 8 {
|
||||||
|
s = s[:8]
|
||||||
|
}
|
||||||
|
t, err = time.ParseInLocation(formatTime, s, tz)
|
||||||
}
|
}
|
||||||
t = t.In(DefaultTimeLoc)
|
t = t.In(DefaultTimeLoc)
|
||||||
|
|
||||||
if err != nil && s != "0000-00-00" && s != "0000-00-00 00:00:00" {
|
if err != nil && s != "00:00:00" && s != "0000-00-00" && s != "0000-00-00 00:00:00" {
|
||||||
tErr = err
|
tErr = err
|
||||||
goto end
|
goto end
|
||||||
}
|
}
|
||||||
@ -1255,7 +1261,7 @@ setValue:
|
|||||||
field.SetString(value.(string))
|
field.SetString(value.(string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case fieldType == TypeDateField || fieldType == TypeDateTimeField:
|
case fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField:
|
||||||
if isNative {
|
if isNative {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
value = time.Time{}
|
value = time.Time{}
|
||||||
|
@ -74,24 +74,32 @@ outFor:
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
v := val.String()
|
v := val.String()
|
||||||
if fi != nil {
|
if fi != nil {
|
||||||
if fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField {
|
if fi.fieldType == TypeTimeField || fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField {
|
||||||
var t time.Time
|
var t time.Time
|
||||||
var err error
|
var err error
|
||||||
if len(v) >= 19 {
|
if len(v) >= 19 {
|
||||||
s := v[:19]
|
s := v[:19]
|
||||||
t, err = time.ParseInLocation(formatDateTime, s, DefaultTimeLoc)
|
t, err = time.ParseInLocation(formatDateTime, s, DefaultTimeLoc)
|
||||||
} else {
|
} else if len(v) >= 10 {
|
||||||
s := v
|
s := v
|
||||||
if len(v) > 10 {
|
if len(v) > 10 {
|
||||||
s = v[:10]
|
s = v[:10]
|
||||||
}
|
}
|
||||||
t, err = time.ParseInLocation(formatDate, s, tz)
|
t, err = time.ParseInLocation(formatDate, s, tz)
|
||||||
|
} else {
|
||||||
|
s := v
|
||||||
|
if len(s) > 8 {
|
||||||
|
s = v[:8]
|
||||||
|
}
|
||||||
|
t, err = time.ParseInLocation(formatTime, s, tz)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if fi.fieldType == TypeDateField {
|
if fi.fieldType == TypeDateField {
|
||||||
v = t.In(tz).Format(formatDate)
|
v = t.In(tz).Format(formatDate)
|
||||||
} else {
|
} else if fi.fieldType == TypeDateTimeField {
|
||||||
v = t.In(tz).Format(formatDateTime)
|
v = t.In(tz).Format(formatDateTime)
|
||||||
|
} else {
|
||||||
|
v = t.In(tz).Format(formatTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,8 +145,10 @@ outFor:
|
|||||||
if v, ok := arg.(time.Time); ok {
|
if v, ok := arg.(time.Time); ok {
|
||||||
if fi != nil && fi.fieldType == TypeDateField {
|
if fi != nil && fi.fieldType == TypeDateField {
|
||||||
arg = v.In(tz).Format(formatDate)
|
arg = v.In(tz).Format(formatDate)
|
||||||
} else {
|
} else if fi.fieldType == TypeDateTimeField {
|
||||||
arg = v.In(tz).Format(formatDateTime)
|
arg = v.In(tz).Format(formatDateTime)
|
||||||
|
} else {
|
||||||
|
arg = v.In(tz).Format(formatTime)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
typ := val.Type()
|
typ := val.Type()
|
||||||
|
@ -25,6 +25,7 @@ const (
|
|||||||
TypeBooleanField = 1 << iota
|
TypeBooleanField = 1 << iota
|
||||||
TypeCharField
|
TypeCharField
|
||||||
TypeTextField
|
TypeTextField
|
||||||
|
TypeTimeField
|
||||||
TypeDateField
|
TypeDateField
|
||||||
TypeDateTimeField
|
TypeDateTimeField
|
||||||
TypeBitField
|
TypeBitField
|
||||||
@ -46,9 +47,9 @@ const (
|
|||||||
|
|
||||||
// Define some logic enum
|
// Define some logic enum
|
||||||
const (
|
const (
|
||||||
IsIntegerField = ^-TypePositiveBigIntegerField >> 4 << 5
|
IsIntegerField = ^-TypePositiveBigIntegerField >> 5 << 6
|
||||||
IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 8 << 9
|
IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 9 << 10
|
||||||
IsRelField = ^-RelReverseMany >> 14 << 15
|
IsRelField = ^-RelReverseMany >> 15 << 16
|
||||||
IsFieldType = ^-RelReverseMany<<1 + 1
|
IsFieldType = ^-RelReverseMany<<1 + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -145,6 +146,59 @@ func (e *CharField) RawValue() interface{} {
|
|||||||
// verify CharField implement Fielder
|
// verify CharField implement Fielder
|
||||||
var _ Fielder = new(CharField)
|
var _ Fielder = new(CharField)
|
||||||
|
|
||||||
|
// A time, represented in go by a time.Time instance.
|
||||||
|
// only time values like 10:00:00
|
||||||
|
// Has a few extra, optional attr tag:
|
||||||
|
//
|
||||||
|
// auto_now:
|
||||||
|
// Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps.
|
||||||
|
// Note that the current date is always used; it’s not just a default value that you can override.
|
||||||
|
//
|
||||||
|
// auto_now_add:
|
||||||
|
// Automatically set the field to now when the object is first created. Useful for creation of timestamps.
|
||||||
|
// Note that the current date is always used; it’s not just a default value that you can override.
|
||||||
|
//
|
||||||
|
// eg: `orm:"auto_now"` or `orm:"auto_now_add"`
|
||||||
|
type TimeField time.Time
|
||||||
|
|
||||||
|
func (e TimeField) Value() time.Time {
|
||||||
|
return time.Time(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TimeField) Set(d time.Time) {
|
||||||
|
*e = TimeField(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TimeField) String() string {
|
||||||
|
return e.Value().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TimeField) FieldType() int {
|
||||||
|
return TypeDateField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TimeField) SetRaw(value interface{}) error {
|
||||||
|
switch d := value.(type) {
|
||||||
|
case time.Time:
|
||||||
|
e.Set(d)
|
||||||
|
case string:
|
||||||
|
v, err := timeParse(d, formatTime)
|
||||||
|
if err != nil {
|
||||||
|
e.Set(v)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("<TimeField.SetRaw> unknown value `%s`", value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TimeField) RawValue() interface{} {
|
||||||
|
return e.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Fielder = new(TimeField)
|
||||||
|
|
||||||
// DateField A date, represented in go by a time.Time instance.
|
// DateField A date, represented in go by a time.Time instance.
|
||||||
// only date values like 2006-01-02
|
// only date values like 2006-01-02
|
||||||
// Has a few extra, optional attr tag:
|
// Has a few extra, optional attr tag:
|
||||||
|
@ -248,6 +248,9 @@ checkType:
|
|||||||
if fieldType == TypeDateTimeField && tags["type"] == "date" {
|
if fieldType == TypeDateTimeField && tags["type"] == "date" {
|
||||||
fieldType = TypeDateField
|
fieldType = TypeDateField
|
||||||
}
|
}
|
||||||
|
if fieldType == TypeTimeField && tags["type"] == "time" {
|
||||||
|
fieldType = TypeTimeField
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch fieldType {
|
switch fieldType {
|
||||||
@ -353,7 +356,7 @@ checkType:
|
|||||||
case TypeTextField:
|
case TypeTextField:
|
||||||
fi.index = false
|
fi.index = false
|
||||||
fi.unique = false
|
fi.unique = false
|
||||||
case TypeDateField, TypeDateTimeField:
|
case TypeTimeField, TypeDateField, TypeDateTimeField:
|
||||||
if attrs["auto_now"] {
|
if attrs["auto_now"] {
|
||||||
fi.autoNow = true
|
fi.autoNow = true
|
||||||
} else if attrs["auto_now_add"] {
|
} else if attrs["auto_now_add"] {
|
||||||
@ -406,7 +409,7 @@ checkType:
|
|||||||
fi.index = false
|
fi.index = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.auto || fi.pk || fi.unique || fieldType == TypeDateField || fieldType == TypeDateTimeField {
|
if fi.auto || fi.pk || fi.unique || fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField {
|
||||||
// can not set default
|
// can not set default
|
||||||
initial.Clear()
|
initial.Clear()
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ type Data struct {
|
|||||||
Boolean bool
|
Boolean bool
|
||||||
Char string `orm:"size(50)"`
|
Char string `orm:"size(50)"`
|
||||||
Text string `orm:"type(text)"`
|
Text string `orm:"type(text)"`
|
||||||
|
Time time.Time `orm:"type(time)"`
|
||||||
Date time.Time `orm:"type(date)"`
|
Date time.Time `orm:"type(date)"`
|
||||||
DateTime time.Time `orm:"column(datetime)"`
|
DateTime time.Time `orm:"column(datetime)"`
|
||||||
Byte byte
|
Byte byte
|
||||||
@ -136,6 +137,7 @@ type DataNull struct {
|
|||||||
Boolean bool `orm:"null"`
|
Boolean bool `orm:"null"`
|
||||||
Char string `orm:"null;size(50)"`
|
Char string `orm:"null;size(50)"`
|
||||||
Text string `orm:"null;type(text)"`
|
Text string `orm:"null;type(text)"`
|
||||||
|
Time time.Time `orm:"null;type(time)"`
|
||||||
Date time.Time `orm:"null;type(date)"`
|
Date time.Time `orm:"null;type(date)"`
|
||||||
DateTime time.Time `orm:"null;column(datetime)"`
|
DateTime time.Time `orm:"null;column(datetime)"`
|
||||||
Byte byte `orm:"null"`
|
Byte byte `orm:"null"`
|
||||||
|
@ -34,6 +34,7 @@ var _ = os.PathSeparator
|
|||||||
var (
|
var (
|
||||||
testDate = formatDate + " -0700"
|
testDate = formatDate + " -0700"
|
||||||
testDateTime = formatDateTime + " -0700"
|
testDateTime = formatDateTime + " -0700"
|
||||||
|
testTime = formatTime + " -0700"
|
||||||
)
|
)
|
||||||
|
|
||||||
type argAny []interface{}
|
type argAny []interface{}
|
||||||
@ -240,6 +241,7 @@ var DataValues = map[string]interface{}{
|
|||||||
"Boolean": true,
|
"Boolean": true,
|
||||||
"Char": "char",
|
"Char": "char",
|
||||||
"Text": "text",
|
"Text": "text",
|
||||||
|
"Time": time.Now(),
|
||||||
"Date": time.Now(),
|
"Date": time.Now(),
|
||||||
"DateTime": time.Now(),
|
"DateTime": time.Now(),
|
||||||
"Byte": byte(1<<8 - 1),
|
"Byte": byte(1<<8 - 1),
|
||||||
@ -267,7 +269,6 @@ func TestDataTypes(t *testing.T) {
|
|||||||
e := ind.FieldByName(name)
|
e := ind.FieldByName(name)
|
||||||
e.Set(reflect.ValueOf(value))
|
e.Set(reflect.ValueOf(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := dORM.Insert(&d)
|
id, err := dORM.Insert(&d)
|
||||||
throwFail(t, err)
|
throwFail(t, err)
|
||||||
throwFail(t, AssertIs(id, 1))
|
throwFail(t, AssertIs(id, 1))
|
||||||
@ -288,6 +289,9 @@ func TestDataTypes(t *testing.T) {
|
|||||||
case "DateTime":
|
case "DateTime":
|
||||||
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
|
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
|
||||||
value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
|
value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
|
||||||
|
case "Time":
|
||||||
|
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime)
|
||||||
|
value = value.(time.Time).In(DefaultTimeLoc).Format(testTime)
|
||||||
}
|
}
|
||||||
throwFail(t, AssertIs(vu == value, true), value, vu)
|
throwFail(t, AssertIs(vu == value, true), value, vu)
|
||||||
}
|
}
|
||||||
@ -1521,6 +1525,7 @@ func TestRawQueryRow(t *testing.T) {
|
|||||||
Boolean bool
|
Boolean bool
|
||||||
Char string
|
Char string
|
||||||
Text string
|
Text string
|
||||||
|
Time time.Time
|
||||||
Date time.Time
|
Date time.Time
|
||||||
DateTime time.Time
|
DateTime time.Time
|
||||||
Byte byte
|
Byte byte
|
||||||
@ -1549,14 +1554,14 @@ func TestRawQueryRow(t *testing.T) {
|
|||||||
Q := dDbBaser.TableQuote()
|
Q := dDbBaser.TableQuote()
|
||||||
|
|
||||||
cols := []string{
|
cols := []string{
|
||||||
"id", "boolean", "char", "text", "date", "datetime", "byte", "rune", "int", "int8", "int16", "int32",
|
"id", "boolean", "char", "text", "time", "date", "datetime", "byte", "rune", "int", "int8", "int16", "int32",
|
||||||
"int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "decimal",
|
"int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "decimal",
|
||||||
}
|
}
|
||||||
sep := fmt.Sprintf("%s, %s", Q, Q)
|
sep := fmt.Sprintf("%s, %s", Q, Q)
|
||||||
query := fmt.Sprintf("SELECT %s%s%s FROM data WHERE id = ?", Q, strings.Join(cols, sep), Q)
|
query := fmt.Sprintf("SELECT %s%s%s FROM data WHERE id = ?", Q, strings.Join(cols, sep), Q)
|
||||||
var id int
|
var id int
|
||||||
values := []interface{}{
|
values := []interface{}{
|
||||||
&id, &Boolean, &Char, &Text, &Date, &DateTime, &Byte, &Rune, &Int, &Int8, &Int16, &Int32,
|
&id, &Boolean, &Char, &Text, &Time, &Date, &DateTime, &Byte, &Rune, &Int, &Int8, &Int16, &Int32,
|
||||||
&Int64, &Uint, &Uint8, &Uint16, &Uint32, &Uint64, &Float32, &Float64, &Decimal,
|
&Int64, &Uint, &Uint8, &Uint16, &Uint32, &Uint64, &Float32, &Float64, &Decimal,
|
||||||
}
|
}
|
||||||
err := dORM.Raw(query, 1).QueryRow(values...)
|
err := dORM.Raw(query, 1).QueryRow(values...)
|
||||||
@ -1567,6 +1572,10 @@ func TestRawQueryRow(t *testing.T) {
|
|||||||
switch col {
|
switch col {
|
||||||
case "id":
|
case "id":
|
||||||
throwFail(t, AssertIs(id, 1))
|
throwFail(t, AssertIs(id, 1))
|
||||||
|
case "time":
|
||||||
|
v = v.(time.Time).In(DefaultTimeLoc)
|
||||||
|
value := dataValues[col].(time.Time).In(DefaultTimeLoc)
|
||||||
|
throwFail(t, AssertIs(v, value, testTime))
|
||||||
case "date":
|
case "date":
|
||||||
v = v.(time.Time).In(DefaultTimeLoc)
|
v = v.(time.Time).In(DefaultTimeLoc)
|
||||||
value := dataValues[col].(time.Time).In(DefaultTimeLoc)
|
value := dataValues[col].(time.Time).In(DefaultTimeLoc)
|
||||||
@ -1614,6 +1623,9 @@ func TestQueryRows(t *testing.T) {
|
|||||||
e := ind.FieldByName(name)
|
e := ind.FieldByName(name)
|
||||||
vu := e.Interface()
|
vu := e.Interface()
|
||||||
switch name {
|
switch name {
|
||||||
|
case "Time":
|
||||||
|
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime)
|
||||||
|
value = value.(time.Time).In(DefaultTimeLoc).Format(testTime)
|
||||||
case "Date":
|
case "Date":
|
||||||
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
||||||
value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
||||||
@ -1638,6 +1650,9 @@ func TestQueryRows(t *testing.T) {
|
|||||||
e := ind.FieldByName(name)
|
e := ind.FieldByName(name)
|
||||||
vu := e.Interface()
|
vu := e.Interface()
|
||||||
switch name {
|
switch name {
|
||||||
|
case "Time":
|
||||||
|
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime)
|
||||||
|
value = value.(time.Time).In(DefaultTimeLoc).Format(testTime)
|
||||||
case "Date":
|
case "Date":
|
||||||
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
||||||
value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
|
||||||
|
Loading…
Reference in New Issue
Block a user