Browse Source

Merge pull request #301 from tealeg/treat-hours-correctly

Treat hours correctly
Geoffrey J. Teale 8 years ago
parent
commit
cbd41c1362
5 changed files with 55 additions and 18 deletions
  1. 18 3
      cell.go
  2. 31 9
      cell_test.go
  3. 3 3
      file.go
  4. 1 1
      sheet.go
  5. 2 2
      xmlStyle.go

+ 18 - 3
cell.go

@@ -361,8 +361,6 @@ func parseTime(c *Cell) (string, error) {
 		{"mmm", "Jan"},
 		{"mmss", "0405"},
 		{"ss", "05"},
-		{"hh", "15"},
-		{"h", "3"},
 		{"mm:", "04:"},
 		{":mm", ":04"},
 		{"mm", "01"},
@@ -371,6 +369,16 @@ func parseTime(c *Cell) (string, error) {
 		{"%%%%", "January"},
 		{"&&&&", "Monday"},
 	}
+	// It is the presence of the "am/pm" indicator that determins
+	// if this is a 12 hour or 24 hours time format, not the
+	// number of 'h' characters.
+	if is12HourTime(format) {
+		format = strings.Replace(format, "hh", "03", 1)
+		format = strings.Replace(format, "h", "3", 1)
+	} else {
+		format = strings.Replace(format, "hh", "15", 1)
+		format = strings.Replace(format, "h", "15", 1)
+	}
 	for _, repl := range replacements {
 		format = strings.Replace(format, repl.xltime, repl.gotime, 1)
 	}
@@ -378,6 +386,7 @@ func parseTime(c *Cell) (string, error) {
 	// possible dangling colon that would remain.
 	if val.Hour() < 1 {
 		format = strings.Replace(format, "]:", "]", 1)
+		format = strings.Replace(format, "[03]", "", 1)
 		format = strings.Replace(format, "[3]", "", 1)
 		format = strings.Replace(format, "[15]", "", 1)
 	} else {
@@ -391,7 +400,7 @@ func parseTime(c *Cell) (string, error) {
 // a time.Time.
 func isTimeFormat(format string) bool {
 	dateParts := []string{
-		"yy", "hh", "am", "pm", "ss", "mm", ":",
+		"yy", "hh", "h", "am/pm", "AM/PM", "A/P", "a/p", "ss", "mm", ":",
 	}
 	for _, part := range dateParts {
 		if strings.Contains(format, part) {
@@ -400,3 +409,9 @@ func isTimeFormat(format string) bool {
 	}
 	return false
 }
+
+// is12HourTime checks whether an Excel time format string is a 12
+// hours form.
+func is12HourTime(format string) bool {
+	return strings.Contains(format, "am/pm") || strings.Contains(format, "AM/PM") || strings.Contains(format, "a/p") || strings.Contains(format, "A/P")
+}

+ 31 - 9
cell_test.go

@@ -259,34 +259,34 @@ func (l *CellSuite) TestFormattedValue(c *C) {
 	fvc.Equals(smallCell, "12:10:04 am")
 
 	cell.NumFmt = "h:mm"
-	fvc.Equals(cell, "6:00")
+	fvc.Equals(cell, "18:00")
 	smallCell.NumFmt = "h:mm"
-	fvc.Equals(smallCell, "12:10")
+	fvc.Equals(smallCell, "00:10")
 	smallCell.NumFmt = "hh:mm"
 	fvc.Equals(smallCell, "00:10")
 
 	cell.NumFmt = "h:mm:ss"
-	fvc.Equals(cell, "6:00:00")
+	fvc.Equals(cell, "18:00:00")
 	cell.NumFmt = "hh:mm:ss"
 	fvc.Equals(cell, "18:00:00")
 
 	smallCell.NumFmt = "hh:mm:ss"
 	fvc.Equals(smallCell, "00:10:04")
 	smallCell.NumFmt = "h:mm:ss"
-	fvc.Equals(smallCell, "12:10:04")
+	fvc.Equals(smallCell, "00:10:04")
 
 	cell.NumFmt = "m/d/yy h:mm"
-	fvc.Equals(cell, "11/22/03 6:00")
+	fvc.Equals(cell, "11/22/03 18:00")
 	cell.NumFmt = "m/d/yy hh:mm"
 	fvc.Equals(cell, "11/22/03 18:00")
 	smallCell.NumFmt = "m/d/yy h:mm"
-	fvc.Equals(smallCell, "12/30/99 12:10")
+	fvc.Equals(smallCell, "12/30/99 00:10")
 	smallCell.NumFmt = "m/d/yy hh:mm"
 	fvc.Equals(smallCell, "12/30/99 00:10")
 	earlyCell.NumFmt = "m/d/yy hh:mm"
 	fvc.Equals(earlyCell, "1/1/00 02:24")
 	earlyCell.NumFmt = "m/d/yy h:mm"
-	fvc.Equals(earlyCell, "1/1/00 2:24")
+	fvc.Equals(earlyCell, "1/1/00 02:24")
 
 	cell.NumFmt = "mm:ss"
 	fvc.Equals(cell, "00:00")
@@ -296,7 +296,7 @@ func (l *CellSuite) TestFormattedValue(c *C) {
 	cell.NumFmt = "[hh]:mm:ss"
 	fvc.Equals(cell, "18:00:00")
 	cell.NumFmt = "[h]:mm:ss"
-	fvc.Equals(cell, "6:00:00")
+	fvc.Equals(cell, "18:00:00")
 	smallCell.NumFmt = "[h]:mm:ss"
 	fvc.Equals(smallCell, "10:04")
 
@@ -362,7 +362,7 @@ func (l *CellSuite) TestFormattedValue(c *C) {
 	fvc.Equals(cell, "22/11/2003")
 
 	cell.NumFmt = "mm/dd/yy hh:mm am/pm"
-	fvc.Equals(cell, "11/22/03 18:00 pm")
+	fvc.Equals(cell, "11/22/03 06:00 pm")
 	cell.NumFmt = "mm/dd/yy h:mm am/pm"
 	fvc.Equals(cell, "11/22/03 6:00 pm")
 
@@ -500,3 +500,25 @@ func (s *CellSuite) TestSetValue(c *C) {
 	cell.SetValue([]string{"test"})
 	c.Assert(cell.Value, Equals, "[test]")
 }
+
+func (s *CellSuite) TestIsTimeFormat(c *C) {
+	c.Assert(isTimeFormat("yy"), Equals, true)
+	c.Assert(isTimeFormat("hh"), Equals, true)
+	c.Assert(isTimeFormat("h"), Equals, true)
+	c.Assert(isTimeFormat("am/pm"), Equals, true)
+	c.Assert(isTimeFormat("AM/PM"), Equals, true)
+	c.Assert(isTimeFormat("A/P"), Equals, true)
+	c.Assert(isTimeFormat("a/p"), Equals, true)
+	c.Assert(isTimeFormat("ss"), Equals, true)
+	c.Assert(isTimeFormat("mm"), Equals, true)
+	c.Assert(isTimeFormat(":"), Equals, true)
+	c.Assert(isTimeFormat("z"), Equals, false)
+}
+
+func (s *CellSuite) TestIs12HourtTime(c *C) {
+	c.Assert(is12HourTime("am/pm"), Equals, true)
+	c.Assert(is12HourTime("AM/PM"), Equals, true)
+	c.Assert(is12HourTime("a/p"), Equals, true)
+	c.Assert(is12HourTime("A/P"), Equals, true)
+	c.Assert(is12HourTime("x"), Equals, false)
+}

+ 3 - 3
file.go

@@ -4,12 +4,12 @@ import (
 	"archive/zip"
 	"bytes"
 	"encoding/xml"
+	"errors"
 	"fmt"
 	"io"
 	"os"
 	"strconv"
 	"strings"
-	"errors"
 )
 
 // File is a high level structure providing a slice of Sheet structs
@@ -219,8 +219,8 @@ func (f *File) MarshallParts() (map[string]string, error) {
 		f.styles = newXlsxStyleSheet(f.theme)
 	}
 	f.styles.reset()
-	if len(f.Sheets)==0 {
-		err:= errors.New("Workbook must contains atleast one worksheet")
+	if len(f.Sheets) == 0 {
+		err := errors.New("Workbook must contains atleast one worksheet")
 		return nil, err
 	}
 	for _, sheet := range f.Sheets {

+ 1 - 1
sheet.go

@@ -237,7 +237,7 @@ func (s *Sheet) makeXLSXSheet(refTable *RefTable, styles *xlsxStyleSheet) *xlsxW
 		if col.Width == 0 {
 			col.Width = ColWidth
 			customWidth = false
-			
+
 		} else {
 			customWidth = true
 		}

+ 2 - 2
xmlStyle.go

@@ -57,9 +57,9 @@ var builtInNumFmt = map[int]string{
 	49: "@",
 }
 
-var builtInNumFmtInv = make(map[string]int,40)
+var builtInNumFmtInv = make(map[string]int, 40)
 
-func init () {
+func init() {
 	for k, v := range builtInNumFmt {
 		builtInNumFmtInv[v] = k
 	}