# Custom types

The following built-in types, their aliases and named types based on them are recognized as ObjectBox and stored as an appropriate internal type:

```go
int, int8, int16, int32, int64
uint, uint8, uint16, uint32, uint64
bool
string, []string
byte, []byte
rune
float32, float64
```

## Defining a converter

To add support for a custom type, you can map properties to one of the built-in types using a `converter` annotation.&#x20;

For example, you could define a color in your entity using a custom `Color` struct and map it to an `int32`. Or you can map the `time.Time` to an `int64`, though losing some precision - less than a millisecond, i. e. a thousandth of a second):

```go
type Task struct {
	Id          uint64
	Text        string
	DateCreated time.Time  `objectbox:"date type:int64 converter:timeInt64"`
}
```

In the entity definition above, we instruct ObjectBox to store the `DateCreated` field as a `int64` while converting it to/from `time.Time` when using in the program. ObjectBox will generate a binding code that will call the following two functions (both start with the prefix `timeInt64` specified above):

```go
// from DB value to runtime value
func timeInt64ToEntityProperty(dbValue int64) (time.Time, error)

// from runtime value to DB value
func timeInt64ToDatabaseValue(goValue time.Time) (int64, error)
```

Just to complete the example, those functions could be implemented like this:

```go
// converts Unix timestamp in milliseconds (ObjectBox date field format) to time.Time
func timeInt64ToEntityProperty(dbValue int64) (goValue time.Time, err error) {
	err = goValue.UnmarshalText([]byte(dbValue))
	if err != nil {
		err = fmt.Errorf("error unmarshalling time %v: %v", dbValue, err)
	}
	return goValue, err
}

// converts time.Time to Unix timestamp in milliseconds 
// i. e. internal format expected by ObjectBox on a date field
func timeInt64ToDatabaseValue(goValue time.Time) (int64, error) {
	var ms = int64(goValue.Nanosecond()) / 1000000
	return goValue.Unix()*1000 + ms, nil
}
```

{% hint style="info" %}
Actually this converter for `time.Time` is already part of the `objectbox` package and used automatically when you mark a `time.Time` property with `` `objectbox:"date"`. ``&#x20;
{% endhint %}

## Queries on custom types <a href="#queries" id="queries"></a>

When you use a converter, the actual value stored in the database is the result of the `...ToDatabaseValue()` call, e.g. `int64` in the previous example. Therefore, when you want to compare the stored data in a query condition, make sure you use the converted value as well:

```go
// Create
id, _ := box.Put(&model.Task{
	Text: "Buy milk",
	DateCreated: time.Now().UTC()
})

// Query
minTime, _ := time.Parse(time.RFC3339, "2018-11-28T12:16:42.145+07:00")
minTimeInt64, _ := objectbox.TimeInt64ConvertToDatabaseValue(minTime)
tasks, _ := box.Query(
	model.Task_.DateCreated.GreaterThan(minTimeInt64)
).Find()
```

## Things to look out for

You must **not interact with the database** (such as using `Box` or `ObjectBox`) inside the converter. The converter methods are called within a transaction, so for example getting or putting entities to a box will fail.

Your converter implementation must be **thread safe** as it can be called from multiple go routines in parallel. Try to avoid using global variables.

`Query` is unaware of custom types. You have to **use the primitive DB type for queries**.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://golang.objectbox.io/custom-types.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
