Merge 15c0f891e1291a4e4f37eee0829df68a63752547 into 53d09952be705d3ec14058d22d7a420e9624bc2a
This commit is contained in:
		
						commit
						586c806998
					
				
							
								
								
									
										86
									
								
								forced_utc_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								forced_utc_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
package gorm_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// table that is not created automatically
 | 
			
		||||
type ExternalData struct {
 | 
			
		||||
	Id   int
 | 
			
		||||
	Time time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestForcedUTC(t *testing.T) {
 | 
			
		||||
	if dialect := os.Getenv("GORM_DIALECT"); dialect != "postgres" {
 | 
			
		||||
		t.Skip("Skipping this because this is to test postgres issues with timestamps without timezones")
 | 
			
		||||
	}
 | 
			
		||||
	db := DB.New()
 | 
			
		||||
	db.DropTableIfExists(&ExternalData{})
 | 
			
		||||
	db.Exec(`
 | 
			
		||||
		CREATE TABLE IF NOT EXISTS external_data(
 | 
			
		||||
		  id serial PRIMARY KEY,
 | 
			
		||||
		  time timestamp without time zone NOT NULL
 | 
			
		||||
		)`)
 | 
			
		||||
 | 
			
		||||
	tm := time.Date(2000, 1, 1, 1, 0, 0, 0, time.FixedZone("test location", +7200))
 | 
			
		||||
 | 
			
		||||
	//Test without forcing utc
 | 
			
		||||
	elem0 := ExternalData{Time: tm}
 | 
			
		||||
	db.Save(&elem0)
 | 
			
		||||
 | 
			
		||||
	elem := ExternalData{}
 | 
			
		||||
	db.Find(&elem, elem0.Id)
 | 
			
		||||
	if elem.Time.Equal(tm) {
 | 
			
		||||
		t.Errorf("Times should not be equal (timezones)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	db.Model(&elem).Update("time", tm)
 | 
			
		||||
	elem = ExternalData{}
 | 
			
		||||
	db.Find(&elem, elem0.Id)
 | 
			
		||||
	if elem.Time.Equal(tm) {
 | 
			
		||||
		t.Errorf("Times should not be equal (timezones)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cnt := 0
 | 
			
		||||
 | 
			
		||||
	db.Model(&ExternalData{}).Where("time = ?", tm).Count(&cnt)
 | 
			
		||||
	if cnt == 0 {
 | 
			
		||||
		t.Errorf("Timezone is cut off, data still should be found (timezones)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	db.Model(&ExternalData{}).Where("time = ?", tm.UTC()).Count(&cnt)
 | 
			
		||||
	if cnt != 0 {
 | 
			
		||||
		t.Errorf("UTC normalized time should not be found (timezones)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Test with forcing utc
 | 
			
		||||
	db.ForceUTC(true)
 | 
			
		||||
 | 
			
		||||
	elem0 = ExternalData{Time: tm}
 | 
			
		||||
	db.Save(&elem0)
 | 
			
		||||
 | 
			
		||||
	elem = ExternalData{}
 | 
			
		||||
	db.Find(&elem, elem0.Id)
 | 
			
		||||
	if !elem.Time.Equal(tm) {
 | 
			
		||||
		t.Errorf("Times should be equal (forced UTC)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	db.Model(&elem).Update("time", tm)
 | 
			
		||||
	elem = ExternalData{}
 | 
			
		||||
	db.Find(&elem, elem0.Id)
 | 
			
		||||
	if !elem.Time.Equal(tm) {
 | 
			
		||||
		t.Errorf("Times should be equal (forced UTC)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	db.Model(&ExternalData{}).Where("time = ?", tm).Count(&cnt)
 | 
			
		||||
	if cnt != 1 {
 | 
			
		||||
		t.Errorf("Record should be found (forced UTC)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	db.Model(&ExternalData{}).Where("time = ?", tm.UTC()).Count(&cnt)
 | 
			
		||||
	if cnt != 1 {
 | 
			
		||||
		t.Errorf("UTC normalized time should be found (forcedUTC)")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								main.go
									
									
									
									
									
								
							@ -25,6 +25,7 @@ type DB struct {
 | 
			
		||||
	source            string
 | 
			
		||||
	values            map[string]interface{}
 | 
			
		||||
	joinTableHandlers map[string]JoinTableHandler
 | 
			
		||||
	forceUTC          bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open initialize a new db connection, need to import driver first, e.g:
 | 
			
		||||
@ -142,6 +143,17 @@ func (s *DB) LogMode(enable bool) *DB {
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ForceUTC set to `true` to force all time values to be normalized as UTC, `false` for regular behavior (default)
 | 
			
		||||
func (s *DB) ForceUTC(enable bool) *DB {
 | 
			
		||||
	s.forceUTC = enable
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasForcedUTC return the state of the forceUTC flag
 | 
			
		||||
func (s *DB) HasForcedUTC() bool {
 | 
			
		||||
	return s.forceUTC
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SingularTable use singular table by default
 | 
			
		||||
func (s *DB) SingularTable(enable bool) {
 | 
			
		||||
	modelStructsMap = newModelStructsMap()
 | 
			
		||||
@ -682,7 +694,7 @@ func (s *DB) GetErrors() []error {
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
func (s *DB) clone() *DB {
 | 
			
		||||
	db := DB{db: s.db, parent: s.parent, logger: s.logger, logMode: s.logMode, values: map[string]interface{}{}, Value: s.Value, Error: s.Error}
 | 
			
		||||
	db := DB{db: s.db, parent: s.parent, logger: s.logger, logMode: s.logMode, values: map[string]interface{}{}, Value: s.Value, Error: s.Error, forceUTC: s.forceUTC}
 | 
			
		||||
 | 
			
		||||
	for key, value := range s.values {
 | 
			
		||||
		db.values[key] = value
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								scope.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								scope.go
									
									
									
									
									
								
							@ -256,12 +256,12 @@ func (scope *Scope) AddToVars(value interface{}) string {
 | 
			
		||||
	if expr, ok := value.(*expr); ok {
 | 
			
		||||
		exp := expr.expr
 | 
			
		||||
		for _, arg := range expr.args {
 | 
			
		||||
			exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1)
 | 
			
		||||
			exp = strings.Replace(exp, "?", scope.AddToVars(scope.toUTC(arg)), 1)
 | 
			
		||||
		}
 | 
			
		||||
		return exp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scope.SQLVars = append(scope.SQLVars, value)
 | 
			
		||||
	scope.SQLVars = append(scope.SQLVars, scope.toUTC(value))
 | 
			
		||||
	return scope.Dialect().BindVar(len(scope.SQLVars))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1280,3 +1280,13 @@ func (scope *Scope) getColumnAsScope(column string) *Scope {
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (scope *Scope) toUTC(v interface{}) interface{} {
 | 
			
		||||
	if !scope.db.HasForcedUTC() {
 | 
			
		||||
		return v
 | 
			
		||||
	}
 | 
			
		||||
	if tm, ok := v.(time.Time); ok {
 | 
			
		||||
		return tm.UTC()
 | 
			
		||||
	}
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user