More specific types for ObjectStorage response object fields (#74)

* more accurate types for objectstorage response object fields (e.g. ContentLength: string -> in64)

* containers unit tests for new field types

* more specific types for accounts headers fields

* update accounts unit tests

* download header unmarshal method and unit test

* object results unmarshal methods
diff --git a/openstack/objectstorage/v1/accounts/results.go b/openstack/objectstorage/v1/accounts/results.go
index f9e5fcd..216414b 100644
--- a/openstack/objectstorage/v1/accounts/results.go
+++ b/openstack/objectstorage/v1/accounts/results.go
@@ -1,6 +1,9 @@
 package accounts
 
 import (
+	"encoding/json"
+	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/gophercloud/gophercloud"
@@ -13,10 +16,36 @@
 
 // UpdateHeader represents the headers returned in the response from an Update request.
 type UpdateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"-"`
 	ContentType   string                  `json:"Content-Type"`
-	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
+	Date          gophercloud.JSONRFC1123 `json:"Date"`
+}
+
+func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+	type tmp UpdateHeader
+	var updateHeader *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &updateHeader)
+	if err != nil {
+		return err
+	}
+
+	*h = UpdateHeader(updateHeader.tmp)
+
+	switch updateHeader.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(updateHeader.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
 }
 
 // Extract will return a struct of headers returned from a call to Get. To obtain
@@ -29,15 +58,75 @@
 
 // GetHeader represents the headers returned in the response from a Get request.
 type GetHeader struct {
-	BytesUsed      string                  `json:"X-Account-Bytes-Used"`
-	ContainerCount string                  `json:"X-Account-Container-Count"`
-	ContentLength  string                  `json:"Content-Length"`
+	BytesUsed      int64                   `json:"-"`
+	ContainerCount int64                   `json:"-"`
+	ContentLength  int64                   `json:"-"`
+	ObjectCount    int64                   `json:"-"`
 	ContentType    string                  `json:"Content-Type"`
-	Date           gophercloud.JSONRFC1123 `json:"Date"`
-	ObjectCount    string                  `json:"X-Account-Object-Count"`
 	TransID        string                  `json:"X-Trans-Id"`
 	TempURLKey     string                  `json:"X-Account-Meta-Temp-URL-Key"`
 	TempURLKey2    string                  `json:"X-Account-Meta-Temp-URL-Key-2"`
+	Date           gophercloud.JSONRFC1123 `json:"Date"`
+}
+
+func (h *GetHeader) UnmarshalJSON(b []byte) error {
+	type tmp GetHeader
+	var getHeader *struct {
+		tmp
+		BytesUsed      string `json:"X-Account-Bytes-Used"`
+		ContentLength  string `json:"Content-Length"`
+		ContainerCount string `json:"X-Account-Container-Count"`
+		ObjectCount    string `json:"X-Account-Object-Count"`
+	}
+	err := json.Unmarshal(b, &getHeader)
+	if err != nil {
+		return err
+	}
+
+	*h = GetHeader(getHeader.tmp)
+
+	switch getHeader.BytesUsed {
+	case "":
+		h.BytesUsed = 0
+	default:
+		h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	fmt.Println("getHeader: ", getHeader.ContentLength)
+	switch getHeader.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch getHeader.ObjectCount {
+	case "":
+		h.ObjectCount = 0
+	default:
+		h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch getHeader.ContainerCount {
+	case "":
+		h.ContainerCount = 0
+	default:
+		h.ContainerCount, err = strconv.ParseInt(getHeader.ContainerCount, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
 }
 
 // GetResult is returned from a call to the Get function.
diff --git a/openstack/objectstorage/v1/accounts/testing/fixtures.go b/openstack/objectstorage/v1/accounts/testing/fixtures.go
index a265199..fff3071 100644
--- a/openstack/objectstorage/v1/accounts/testing/fixtures.go
+++ b/openstack/objectstorage/v1/accounts/testing/fixtures.go
@@ -16,6 +16,7 @@
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
 
 		w.Header().Set("X-Account-Container-Count", "2")
+		w.Header().Set("X-Account-Object-Count", "5")
 		w.Header().Set("X-Account-Bytes-Used", "14")
 		w.Header().Set("X-Account-Meta-Subject", "books")
 		w.Header().Set("Date", "Fri, 17 Jan 2014 16:09:56 GMT")
diff --git a/openstack/objectstorage/v1/accounts/testing/requests_test.go b/openstack/objectstorage/v1/accounts/testing/requests_test.go
index cf3fe05..dc5d9de 100644
--- a/openstack/objectstorage/v1/accounts/testing/requests_test.go
+++ b/openstack/objectstorage/v1/accounts/testing/requests_test.go
@@ -2,20 +2,33 @@
 
 import (
 	"testing"
+	"time"
 
+	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts"
 	th "github.com/gophercloud/gophercloud/testhelper"
 	fake "github.com/gophercloud/gophercloud/testhelper/client"
 )
 
+var (
+	loc, _ = time.LoadLocation("GMT")
+)
+
 func TestUpdateAccount(t *testing.T) {
 	th.SetupHTTP()
 	defer th.TeardownHTTP()
 	HandleUpdateAccountSuccessfully(t)
 
 	options := &accounts.UpdateOpts{Metadata: map[string]string{"gophercloud-test": "accounts"}}
-	_, err := accounts.Update(fake.ServiceClient(), options).Extract()
+	res := accounts.Update(fake.ServiceClient(), options)
+	th.AssertNoErr(t, res.Err)
+
+	expected := &accounts.UpdateHeader{
+		Date: gophercloud.JSONRFC1123(time.Date(2014, time.January, 17, 16, 9, 56, 0, loc)), // Fri, 17 Jan 2014 16:09:56 GMT
+	}
+	actual, err := res.Extract()
 	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, expected, actual)
 }
 
 func TestGetAccount(t *testing.T) {
@@ -30,4 +43,14 @@
 	th.CheckDeepEquals(t, expectedMetadata, actualMetadata)
 	_, err := res.Extract()
 	th.AssertNoErr(t, err)
+
+	expected := &accounts.GetHeader{
+		ContainerCount: 2,
+		ObjectCount:    5,
+		BytesUsed:      14,
+		Date:           gophercloud.JSONRFC1123(time.Date(2014, time.January, 17, 16, 9, 56, 0, loc)), // Fri, 17 Jan 2014 16:09:56 GMT
+	}
+	actual, err := res.Extract()
+	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, expected, actual)
 }
diff --git a/openstack/objectstorage/v1/containers/results.go b/openstack/objectstorage/v1/containers/results.go
index 9eec3f4..ebe6eba 100644
--- a/openstack/objectstorage/v1/containers/results.go
+++ b/openstack/objectstorage/v1/containers/results.go
@@ -1,7 +1,9 @@
 package containers
 
 import (
+	"encoding/json"
 	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/gophercloud/gophercloud"
@@ -11,10 +13,10 @@
 // Container represents a container resource.
 type Container struct {
 	// The total number of bytes stored in the container.
-	Bytes int `json:"bytes"`
+	Bytes int64 `json:"bytes"`
 
 	// The total number of objects stored in the container.
-	Count int `json:"count"`
+	Count int64 `json:"count"`
 
 	// The name of the container.
 	Name string `json:"name"`
@@ -87,15 +89,68 @@
 // GetHeader represents the headers returned in the response from a Get request.
 type GetHeader struct {
 	AcceptRanges     string                  `json:"Accept-Ranges"`
-	BytesUsed        string                  `json:"X-Account-Bytes-Used"`
-	ContentLength    string                  `json:"Content-Length"`
+	BytesUsed        int64                   `json:"-"`
+	ContentLength    int64                   `json:"-"`
 	ContentType      string                  `json:"Content-Type"`
 	Date             gophercloud.JSONRFC1123 `json:"Date"`
-	ObjectCount      string                  `json:"X-Container-Object-Count"`
-	Read             string                  `json:"X-Container-Read"`
+	ObjectCount      int64                   `json:"-"`
+	Read             []string                `json:"-"`
 	TransID          string                  `json:"X-Trans-Id"`
 	VersionsLocation string                  `json:"X-Versions-Location"`
-	Write            string                  `json:"X-Container-Write"`
+	Write            []string                `json:"-"`
+}
+
+func (h *GetHeader) UnmarshalJSON(b []byte) error {
+	type tmp GetHeader
+	var getHeader *struct {
+		tmp
+		BytesUsed     string `json:"X-Container-Bytes-Used"`
+		ContentLength string `json:"Content-Length"`
+		ObjectCount   string `json:"X-Container-Object-Count"`
+		Write         string `json:"X-Container-Write"`
+		Read          string `json:"X-Container-Read"`
+	}
+	err := json.Unmarshal(b, &getHeader)
+	if err != nil {
+		return err
+	}
+
+	*h = GetHeader(getHeader.tmp)
+
+	switch getHeader.BytesUsed {
+	case "":
+		h.BytesUsed = 0
+	default:
+		h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch getHeader.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch getHeader.ObjectCount {
+	case "":
+		h.ObjectCount = 0
+	default:
+		h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	h.Read = strings.Split(getHeader.Read, ",")
+	h.Write = strings.Split(getHeader.Write, ",")
+
+	return nil
 }
 
 // GetResult represents the result of a get operation.
@@ -129,12 +184,38 @@
 
 // CreateHeader represents the headers returned in the response from a Create request.
 type CreateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"-"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *CreateHeader) UnmarshalJSON(b []byte) error {
+	type tmp CreateHeader
+	var header *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &header)
+	if err != nil {
+		return err
+	}
+
+	*h = CreateHeader(header.tmp)
+
+	switch header.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // CreateResult represents the result of a create operation. To extract the
 // the headers from the HTTP response, you can invoke the 'ExtractHeader'
 // method on the result struct.
@@ -152,12 +233,38 @@
 
 // UpdateHeader represents the headers returned in the response from a Update request.
 type UpdateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"-"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+	type tmp UpdateHeader
+	var header *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &header)
+	if err != nil {
+		return err
+	}
+
+	*h = UpdateHeader(header.tmp)
+
+	switch header.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // UpdateResult represents the result of an update operation. To extract the
 // the headers from the HTTP response, you can invoke the 'ExtractHeader'
 // method on the result struct.
@@ -175,12 +282,38 @@
 
 // DeleteHeader represents the headers returned in the response from a Delete request.
 type DeleteHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"-"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *DeleteHeader) UnmarshalJSON(b []byte) error {
+	type tmp DeleteHeader
+	var header *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &header)
+	if err != nil {
+		return err
+	}
+
+	*h = DeleteHeader(header.tmp)
+
+	switch header.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // DeleteResult represents the result of a delete operation. To extract the
 // the headers from the HTTP response, you can invoke the 'ExtractHeader'
 // method on the result struct.
diff --git a/openstack/objectstorage/v1/containers/testing/fixtures.go b/openstack/objectstorage/v1/containers/testing/fixtures.go
index fe579d8..b68230a 100644
--- a/openstack/objectstorage/v1/containers/testing/fixtures.go
+++ b/openstack/objectstorage/v1/containers/testing/fixtures.go
@@ -103,7 +103,10 @@
 		th.TestHeader(t, r, "Accept", "application/json")
 
 		w.Header().Add("X-Container-Meta-Foo", "bar")
-		w.Header().Add("X-Trans-Id", "1234567")
+		w.Header().Set("Content-Length", "0")
+		w.Header().Set("Content-Type", "text/html; charset=UTF-8")
+		w.Header().Set("Date", "Wed, 17 Aug 2016 19:25:43 GMT")
+		w.Header().Set("X-Trans-Id", "tx554ed59667a64c61866f1-0058b4ba37")
 		w.WriteHeader(http.StatusNoContent)
 	})
 }
@@ -137,6 +140,15 @@
 		th.TestMethod(t, r, "HEAD")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
 		th.TestHeader(t, r, "Accept", "application/json")
+		w.Header().Set("Accept-Ranges", "bytes")
+		w.Header().Set("Content-Type", "application/json; charset=utf-8")
+		w.Header().Set("Date", "Wed, 17 Aug 2016 19:25:43 GMT")
+		w.Header().Set("X-Container-Bytes-Used", "100")
+		w.Header().Set("X-Container-Object-Count", "4")
+		w.Header().Set("X-Container-Read", "test")
+		w.Header().Set("X-Container-Write", "test2,user4")
+		w.Header().Set("X-Timestamp", "1471298837.95721")
+		w.Header().Set("X-Trans-Id", "tx554ed59667a64c61866f1-0057b4ba37")
 		w.WriteHeader(http.StatusNoContent)
 	})
 }
diff --git a/openstack/objectstorage/v1/containers/testing/requests_test.go b/openstack/objectstorage/v1/containers/testing/requests_test.go
index 0d32882..abac922 100644
--- a/openstack/objectstorage/v1/containers/testing/requests_test.go
+++ b/openstack/objectstorage/v1/containers/testing/requests_test.go
@@ -2,14 +2,19 @@
 
 import (
 	"testing"
+	"time"
 
+	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers"
 	"github.com/gophercloud/gophercloud/pagination"
 	th "github.com/gophercloud/gophercloud/testhelper"
 	fake "github.com/gophercloud/gophercloud/testhelper/client"
 )
 
-var metadata = map[string]string{"gophercloud-test": "containers"}
+var (
+	metadata = map[string]string{"gophercloud-test": "containers"}
+	loc, _   = time.LoadLocation("GMT")
+)
 
 func TestListContainerInfo(t *testing.T) {
 	th.SetupHTTP()
@@ -83,10 +88,17 @@
 
 	options := containers.CreateOpts{ContentType: "application/json", Metadata: map[string]string{"foo": "bar"}}
 	res := containers.Create(fake.ServiceClient(), "testContainer", options)
-	c, err := res.Extract()
-	th.CheckNoErr(t, err)
 	th.CheckEquals(t, "bar", res.Header["X-Container-Meta-Foo"][0])
-	th.CheckEquals(t, "1234567", c.TransID)
+
+	expected := &containers.CreateHeader{
+		ContentLength: 0,
+		ContentType:   "text/html; charset=UTF-8",
+		Date:          gophercloud.JSONRFC1123(time.Date(2016, time.August, 17, 19, 25, 43, 0, loc)), //Wed, 17 Aug 2016 19:25:43 GMT
+		TransID:       "tx554ed59667a64c61866f1-0058b4ba37",
+	}
+	actual, err := res.Extract()
+	th.CheckNoErr(t, err)
+	th.AssertDeepEquals(t, expected, actual)
 }
 
 func TestDeleteContainer(t *testing.T) {
@@ -113,6 +125,21 @@
 	defer th.TeardownHTTP()
 	HandleGetContainerSuccessfully(t)
 
-	_, err := containers.Get(fake.ServiceClient(), "testContainer").ExtractMetadata()
+	res := containers.Get(fake.ServiceClient(), "testContainer")
+	_, err := res.ExtractMetadata()
 	th.CheckNoErr(t, err)
+
+	expected := &containers.GetHeader{
+		AcceptRanges: "bytes",
+		BytesUsed:    100,
+		ContentType:  "application/json; charset=utf-8",
+		Date:         gophercloud.JSONRFC1123(time.Date(2016, time.August, 17, 19, 25, 43, 0, loc)), //Wed, 17 Aug 2016 19:25:43 GMT
+		ObjectCount:  4,
+		Read:         []string{"test"},
+		TransID:      "tx554ed59667a64c61866f1-0057b4ba37",
+		Write:        []string{"test2", "user4"},
+	}
+	actual, err := res.Extract()
+	th.CheckNoErr(t, err)
+	th.AssertDeepEquals(t, expected, actual)
 }
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index 3cfe1f4..1390faa 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -1,9 +1,11 @@
 package objects
 
 import (
+	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
+	"strconv"
 	"strings"
 
 	"github.com/gophercloud/gophercloud"
@@ -24,7 +26,7 @@
 	// LastModified is the RFC3339Milli time the object was last modified, represented
 	// as a string. For any given object (obj), this value may be parsed to a time.Time:
 	// lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified)
-	LastModified string `json:"last_modified"`
+	LastModified gophercloud.JSONRFC1123 `json:"last_modified"`
 
 	// Name is the unique name for the object.
 	Name string `json:"name"`
@@ -101,7 +103,7 @@
 	AcceptRanges       string                  `json:"Accept-Ranges"`
 	ContentDisposition string                  `json:"Content-Disposition"`
 	ContentEncoding    string                  `json:"Content-Encoding"`
-	ContentLength      string                  `json:"Content-Length"`
+	ContentLength      int64                   `json:"-"`
 	ContentType        string                  `json:"Content-Type"`
 	Date               gophercloud.JSONRFC1123 `json:"Date"`
 	DeleteAt           gophercloud.JSONUnix    `json:"X-Delete-At"`
@@ -112,6 +114,32 @@
 	TransID            string                  `json:"X-Trans-Id"`
 }
 
+func (h *DownloadHeader) UnmarshalJSON(b []byte) error {
+	type tmp DownloadHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = DownloadHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // DownloadResult is a *http.Response that is returned from a call to the Download function.
 type DownloadResult struct {
 	gophercloud.HeaderResult
@@ -148,7 +176,7 @@
 type GetHeader struct {
 	ContentDisposition string                  `json:"Content-Disposition"`
 	ContentEncoding    string                  `json:"Content-Encoding"`
-	ContentLength      string                  `json:"Content-Length"`
+	ContentLength      int64                   `json:"Content-Length"`
 	ContentType        string                  `json:"Content-Type"`
 	Date               gophercloud.JSONRFC1123 `json:"Date"`
 	DeleteAt           gophercloud.JSONUnix    `json:"X-Delete-At"`
@@ -159,6 +187,32 @@
 	TransID            string                  `json:"X-Trans-Id"`
 }
 
+func (h *GetHeader) UnmarshalJSON(b []byte) error {
+	type tmp GetHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = GetHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // GetResult is a *http.Response that is returned from a call to the Get function.
 type GetResult struct {
 	gophercloud.HeaderResult
@@ -190,7 +244,7 @@
 
 // CreateHeader represents the headers returned in the response from a Create request.
 type CreateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"Content-Length"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	ETag          string                  `json:"Etag"`
@@ -198,6 +252,32 @@
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *CreateHeader) UnmarshalJSON(b []byte) error {
+	type tmp CreateHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = CreateHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // CreateResult represents the result of a create operation.
 type CreateResult struct {
 	checksum string
@@ -217,12 +297,38 @@
 
 // UpdateHeader represents the headers returned in the response from a Update request.
 type UpdateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"Content-Length"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+	type tmp UpdateHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = UpdateHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // UpdateResult represents the result of an update operation.
 type UpdateResult struct {
 	gophercloud.HeaderResult
@@ -238,12 +344,38 @@
 
 // DeleteHeader represents the headers returned in the response from a Delete request.
 type DeleteHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"Content-Length"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *DeleteHeader) UnmarshalJSON(b []byte) error {
+	type tmp DeleteHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = DeleteHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // DeleteResult represents the result of a delete operation.
 type DeleteResult struct {
 	gophercloud.HeaderResult
@@ -269,6 +401,32 @@
 	TransID                string                  `json:"X-Trans-Id"`
 }
 
+func (h *CopyHeader) UnmarshalJSON(b []byte) error {
+	type tmp CopyHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = CopyHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // CopyResult represents the result of a copy operation.
 type CopyResult struct {
 	gophercloud.HeaderResult
diff --git a/openstack/objectstorage/v1/objects/testing/fixtures.go b/openstack/objectstorage/v1/objects/testing/fixtures.go
index cf1d6c5..d3144cb 100644
--- a/openstack/objectstorage/v1/objects/testing/fixtures.go
+++ b/openstack/objectstorage/v1/objects/testing/fixtures.go
@@ -6,12 +6,18 @@
 	"io"
 	"net/http"
 	"testing"
+	"time"
 
+	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
 	th "github.com/gophercloud/gophercloud/testhelper"
 	fake "github.com/gophercloud/gophercloud/testhelper/client"
 )
 
+var (
+	loc, _ = time.LoadLocation("GMT")
+)
+
 // HandleDownloadObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
 // responds with a `Download` response.
 func HandleDownloadObjectSuccessfully(t *testing.T) {
@@ -19,6 +25,7 @@
 		th.TestMethod(t, r, "GET")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
 		th.TestHeader(t, r, "Accept", "application/json")
+		w.Header().Set("Date", "Wed, 10 Nov 2009 23:00:00 GMT")
 		w.WriteHeader(http.StatusOK)
 		fmt.Fprintf(w, "Successful download with Gophercloud")
 	})
@@ -29,14 +36,14 @@
 var ExpectedListInfo = []objects.Object{
 	{
 		Hash:         "451e372e48e0f6b1114fa0724aa79fa1",
-		LastModified: "2009-11-10 23:00:00 +0000 UTC",
+		LastModified: gophercloud.JSONRFC1123(time.Date(2009, time.November, 10, 23, 0, 0, 0, loc)), //"2009-11-10 23:00:00 +0000 UTC"
 		Bytes:        14,
 		Name:         "goodbye",
 		ContentType:  "application/octet-stream",
 	},
 	{
 		Hash:         "451e372e48e0f6b1114fa0724aa79fa1",
-		LastModified: "2009-11-10 23:00:00 +0000 UTC",
+		LastModified: gophercloud.JSONRFC1123(time.Date(2009, time.November, 10, 23, 0, 0, 0, loc)),
 		Bytes:        14,
 		Name:         "hello",
 		ContentType:  "application/octet-stream",
@@ -63,14 +70,14 @@
 			fmt.Fprintf(w, `[
       {
         "hash": "451e372e48e0f6b1114fa0724aa79fa1",
-        "last_modified": "2009-11-10 23:00:00 +0000 UTC",
+        "last_modified": "Wed, 10 Nov 2009 23:00:00 GMT",
         "bytes": 14,
         "name": "goodbye",
         "content_type": "application/octet-stream"
       },
       {
         "hash": "451e372e48e0f6b1114fa0724aa79fa1",
-        "last_modified": "2009-11-10 23:00:00 +0000 UTC",
+        "last_modified": "Wed, 10 Nov 2009 23:00:00 GMT",
         "bytes": 14,
         "name": "hello",
         "content_type": "application/octet-stream"
diff --git a/openstack/objectstorage/v1/objects/testing/requests_test.go b/openstack/objectstorage/v1/objects/testing/requests_test.go
index 2b9306f..7762d08 100644
--- a/openstack/objectstorage/v1/objects/testing/requests_test.go
+++ b/openstack/objectstorage/v1/objects/testing/requests_test.go
@@ -5,7 +5,9 @@
 	"io"
 	"strings"
 	"testing"
+	"time"
 
+	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
 	"github.com/gophercloud/gophercloud/pagination"
 	th "github.com/gophercloud/gophercloud/testhelper"
@@ -37,6 +39,15 @@
 	bytes, err := response.ExtractContent()
 	th.AssertNoErr(t, err)
 	th.CheckEquals(t, "Successful download with Gophercloud", string(bytes))
+
+	expected := &objects.DownloadHeader{
+		ContentLength: 36,
+		ContentType:   "text/plain; charset=utf-8",
+		Date:          gophercloud.JSONRFC1123(time.Date(2009, time.November, 10, 23, 0, 0, 0, loc)),
+	}
+	actual, err := response.Extract()
+	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, expected, actual)
 }
 
 func TestListObjectInfo(t *testing.T) {