Skip to content

Dates in VectorSurv

To allow users to store the most granular data possible, VectorSurv generally stores time information as a UTC Timestamp ('2000-12-25T00:00:00.000Z') rather than as a calendar date ('2000-12-25'). This distinction is particularly useful for recording events with precise timeframes, such as tick flagging events. However, users should be aware that timestamps require more careful handling, especially when dealing with time zones or daylight saving time.

Temporal fields in API requests

Timestamp or Calendar Date?

Although the API is generally permissive to both timestamps and calendar dates, API users are strongly encouraged to use timestamps when possible to maintain the integrity of the data. For instance, when POSTing a collection, if a collection_date is provided in the form of a calendar date, the backend API will automatically convert it to a timestamp at midnight UTC. This conversion can be observed in the response body.

Sample Collection POST and response

If a collection_date is provided as a calendar date (YYYY-MM-DD), the API will store it as YYYY-MM-DDT00:00:00.000Z (midnight UTC). Keep in mind that this may differ from your local midnight depending on your time zone. When using a timestamp, check your own UTC offset to ensure that information is correctly assigned.

sample_collection_timestamp_POST.json
{
  "collection_date":  "2000-12-25T08:00:00.000Z",
  ...
}
sample_collection_timestamp_response.json
{
  "add_date": "2023-01-01T05:55:29.895Z",
  "updated": "2023-01-01T05:55:29.895Z",
  "id": 456789,
  "collection_date": "2000-12-25T08:00:00.000Z",
  ...
}

A POST with a collection_date in the form of a calendar date will see a midnight UTC timestamp in the response.

sample_collection_calendar_POST.json
{
  "collection_date": "2000-12-25",
  ...
}
sample_collection_calendar_response.json
{
  "add_date": "2023-01-01T05:55:29.895Z",
  "updated": "2023-01-01T05:55:29.895Z",
  "id": 456789,
  "collection_date": "2000-12-25T00:00:00.000Z",
  ...
}

(For a more detailed example on creating a collection, check out the general surveillance example.)

GET requests for data in a specific time period

Timestamps should be used instead of calendar dates when retrieving data for a specific time period, such as a few hours within a day. Using only a calendar date (YYYY-MM-DD) may exclude records outside of the assumed time range. This can often happen due to time zone differences or daylight saving time shifts. Consider checking your own local UTC offset to ensure that you find the data you are looking for. To retrieve data within a specific time range, use $between (for a range) or a combination of $gte (greater than or equal to) and $lte (less than or equal to). (For more detailed query examples, check out the expanded search examples.)

Sample Collection GET by time period

getCollectionsInTimePeriod.js
async function getCollections() {
  const url = "https://api.vectorsurv.org/v1/arthropod/collection";

  const config = {
    headers: {
      Authorization: "Bearer [user_auth_token]", // Substitute a valid auth token
      "Content-Type": "application/json",
    },
    params: {
      // 8 hour period
      "query[collection_date][$gte]": "2000-12-25T08:00:00.000Z", // Begin time range
      "query[collection_date][$lte]": "2000-12-25T16:00:00.000Z", // End time range
      // "query[collection_date][$between][0]": "2000-12-25T08:00:00.000Z", // Between is also valid
      // "query[collection_date][$between][1]": "2000-12-25T16:00:00.000Z",
    },
  };

  try {
    const response = await axios.get(url, config);
    console.log("Response:", response.data);
  } catch (error) {
    console.error("Error:", error.response.data);
  }
}
getCollectionsInTimePeriod.r
library(httr)
library(jsonlite)

getCollections <- function(token) {
  headers = c(
    Authorization = paste("Bearer", token),
    "Content-Type" = "application/json"
  )

  url <- "https://api.vectorsurv.org/v1/arthropod/collection"

  query <- list(
    `populate[]` = list("arthropods"),
    search = "first albo detection",
    `searchFields[]` = list("comments"),
    # 8 hour period
    `query[collection_date][$gte]` = "2000-12-25T08:00:00.000Z", # Begin time range
    `query[collection_date][$lte]` = "2000-12-25T16:00:00.000Z", # End time range
    # `query[collection_date][$between][0]` = "2000-12-25T08:00:00.000Z", # Between is also valid
    # `query[collection_date][$between][1]` = "2000-12-25T16:00:00.000Z"
  )

  tryCatch({
    # Make the API request
    response <- GET(url, add_headers(headers), query = query)

    # Check the response status code and category
    status_code <- http_status(response)$status_code
    status_category <- http_status(response)$category

    # Check the status code of the response
    if (status_category == "Success") {
      # Response status is successful (e.g., status code 200)
      content <- httr::content(response, "text")
      # Use this data frame as needed
      content_df = fromJSON(content)
      print(content)
    } else {
      # Request failed, display an error message
      response_content <- httr::content(response, 'text')
      message("Error response content:", response_content)
    }
  }, error = function(e) {
    # Any other exceptions that might occur during the API request
    message("An error occurred during the API request. Error message:", e$message)
  })
}

getCollections("[user_auth_token]") # Substitute a valid auth token