Format Datetime Objects
Introduction
In this recipe, you'll learn how to convert an existing datetime object from your supergraph into a human-readable format. This approach is perfect when you want to streamline your frontend by formatting data at the API level, allowing the UI to easily render the formatted result with minimal effort.
Before continuing, ensure you have:
- A local Hasura DDN project.
- A lambda connector added to your project.
- A type in your supergraph that is a valid datetime object.
NB: The type will vary with your database-of-choice, but anything that is ISO-8601-compliant will generally work for what's listed below. You can adapt this recipe to fit your individual needs.
Recipe
Step 1. Write the function
- TypeScript
- Python
- Go
/**
* @readonly
*/
export function formattedDate(dateString: string): string {
const date = new Date(dateString);
return date.toLocaleString("en-US", {
year: "numeric",
month: "long",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: true,
});
}
from hasura_ndc import start
from hasura_ndc.function_connector import FunctionConnector
from datetime import datetime
connector = FunctionConnector()
@connector.register_query
async def formatted_date(dateString: str) -> str:
date = datetime.fromisoformat(date_string)
return date.strftime("%B %d, %Y %I:%M %p")
if __name__ == "__main__":
start(connector)
package functions
import (
"context"
"fmt"
"time"
"hasura-ndc.dev/ndc-go/types"
)
// DatetimeArguments defines the input arguments for the function
type DatetimeArguments struct {
DateString string `json:"date_string"` // required argument
}
// DatetimeResult defines the output result for the function
type DatetimeResult string
// FunctionFormattedDate formats a datetime string
func FunctionFormattedDate(ctx context.Context, state *types.State, arguments *DatetimeArguments) (*DatetimeResult, error) {
date, err := time.Parse(time.RFC3339, arguments.DateString)
if err != nil {
return nil, fmt.Errorf("failed to parse date: %v", err)
}
formattedDate := date.Format("January 02, 2006 03:04 PM")
result := DatetimeResult(formattedDate)
return &result, nil
}
Step 2. Track your function
To add your function, generate the related metadata that will link together any functions in your lambda connector's source files and your API:
ddn connector introspect <connector_name>
Then, you can generate an hml
file for the function using the following command:
ddn command add <connector_name> "*"
Step 3. Create a relationship (optional)
Assuming the input argument's type matches that of a type belonging to one or more of your models, you can create a relationship to the command. This will enable you to make nested queries that will invoke your custom business logic using the value of the field from the related model!
Create a relationship in the corresponding model's HML file.
---
kind: Relationship
version: v1
definition:
name: formattedDate
sourceType: Orders
target:
command:
name: FormattedDate
mapping:
- source:
fieldPath:
- fieldName: createdAt
target:
argument:
argumentName: dateString
Step 4. Test your function
Create a new build of your supergraph:
ddn supergraph build local
In your project's explorer, you should see the new function exposed as a type and should be able to make a query like this:
If you created a relationship, you can make a query like this, too:
Wrapping up
In this guide, you learned how to enhance your API and enrich the data it serves for its consumers by incorporating custom business logic directly into your supergraph. By leveraging lambda connectors with relationships, you can not only add custom business logic, but easily pass values to it and return this information as part of existing models.
Learn more about lambda connectors
- TypeScript Node.js connector.
- Python connector.
- Go connector.