ArcGIS Blog

Developers

ArcGIS Maps SDK for .NET

It's about time: Explore new features for date and time management in the ArcGIS Maps SDK for .NET

By Matvei Stefarov

The ArcGIS Maps SDKs for Native Apps 200.4 release introduces support for three new field types that enhance the way date and time data is stored and managed:

  • DateOnly stores date values without any associated time component. This is useful when only the date information is relevant, such as birthdates or inspection dates.
  • TimeOnly stores time values without any associated date component. This can be used for scenarios where only the time-of-day matters, such as business hours or scheduled events.
  • TimestampOffset stores both date and time values along with the time zone information. This field type is particularly useful for mapping events that occur across multiple time zones, such as earthquakes or car accidents.

This article focuses on details of how these field types work in the .NET Maps SDK, but they are also supported across the ArcGIS Platform including ArcGIS Online, ArcGIS Pro, and other Native Maps SDKs.

DateOnly and TimeOnly

When targeting .NET 8.0+, the values of “DateOnly” and “TimeOnly” attributes are represented by System.DateOnly and System.TimeOnly. However, the .NET Maps SDK also supports targeting .NET Framework and UWP, which lack these built-in types. For these legacy platforms we provide API-compatible replacements: Esri.ArcGISRuntime.DateOnly and Esri.ArcGISRuntime.TimeOnly. These implementations provide the same APIs, so you can write “DateOnly” and “TimeOnly” in the source code of multi-targeted and shared projects. The compiler will use types from either “System” or “Esri.ArcGISRuntime” depending on the target configuration. Here are some examples of code using type names, constructors, and methods that work on all platforms:

// Set a DateOnly attribute
feature["DateOnlyField"] = new DateOnly(1991, 8, 24);

// Create a TimeOnly from ISO string
graphic["TimeOnlyField"] = TimeOnly.Parse("23:31:30");

// Get maximum allowed value for a range-restricted DateOnly field
DateOnly? GetMaxDate(Field field)
{
    if (field.Domain is RangeDomain<DateOnly> rangeDomain)
        return rangeDomain.MaxValue;
    else
        return null;
}

Note that although System.TimeOnly struct can represent time values with 100 nanosecond precision, the TimeOnly field type has 1-second resolution. Values will be rounded down to the nearest second when editing TimeOnly attributes. The DateOnly and TimeOnly field types are not time zone aware.

TimestampOffset

TimestampOffset fields combine a date, a time, and a difference in hours and minutes from UTC+00:00 (Universal Coordinated Time, equivalent to Greenwich Mean Time).

There is no better built-in type than System.DateTimeOffset to represent values of new TimestampOffset attributes. However, previous versions of the .NET Maps SDK allowed both System.DateTimeOffset values and System.DateTime values for fields of type “Date”. A change was necessary to avoid confusion between these similar types, prevent unintended implicit conversion, and preserve time zone information. With the latest release, we have introduced an opt-in ArcGISRuntimeEnvironment.EnableTimestampOffsetSupport flag that unlocks use of TimestampOffset fields, but also necessarily changes the behavior of Date fields.

When EnableTimestampOffsetSupport is false (default in v200.4):

  • Values of Date attributes are returned as DateTimeOffset (always UTC).
  • Values of TimestampOffset attributes are also returned as DateTimeOffset.
  • Either DateTime or DateTimeOffset values can be used when editing Date fields.
  • Editing data with TimestampOffset fields is not supported. A NotSupportedException will be thrown.
  • Creating TimestampOffset fields, domains, renderers, or Arcade expressions is not supported.

When EnableTimestampOffsetSupport is changed to true:

  • Values of Date attributes are returned as DateTime (UTC). Trying to set a Date attribute to a DateTimeOffset value fails with a “Geodatabase data type mismatch” exception.
  • Values of TimestampOffset attributes are also returned as DateTimeOffset.
  • Only DateTime values can be used to edit Date attributes. They are converted to UTC.
  • DateTimeOffset values can be used to edit TimestampOffset fields.
  • Creating TimestampOffset fields, domains, renderers, and Arcade expressions is supported.

Let’s look at some examples of code that may be affected by these behavior changes. First, the original code that works when EnableTimestampOffsetSupport is off:

feature["Date1"] = DateTimeOffset.Now;
feature["Date2"] = DateTimeOffset.Parse("7/14/2016 12:00:00 AM -08:00");
var isDate = feature.GetAttributeValue("Date3") is DateTimeOffset;
var maxDate = (DateTimeOffset)statisticRecord.Statistics["MaxDate"];

Now the same code, updated to enable TimestampOffset support:

// Use DateTime instead of DateTimeOffset when setting attributes
feature["Date1"] = DateTime.UtcNow;
feature["Date2"] = DateTimeOffset.Parse("7/14/2016 12:00:00 AM -08:00").UtcDateTime;

// Change the expected type of the attribute value to DateTime
var isDate = feature.GetAttributeValue("Date3") is DateTime;

// No changes needed because DateTime can be safely cast to DateTimeOffset.
var maxDate = (DateTimeOffset)statisticRecord.Statistics["MaxDate"];

The EnableTimestampOffsetSupport flag currently defaults to false, so your existing codebase will continue working as-is when you upgrade to 200.4. To enable support for TimestampOffset fields, set this property to true when initializing the app. We encourage developers to review and adopt parts of their app that work with dates because the default value will change to true in the next release.

Time and Date in Arcade Expressions

ArcGIS Arcade significantly updated and expanded functionality related to date and time recently. Starting with the .NET Maps SDK 200.4, ArcadeEvaluator can now accept and return DateTime, DateOnly, TimeOnly, and DateTimeOffset values.

In ArcGIS Arcade, the Date data type is always time zone-aware and prefers local time zones. Inputs without time zone information (i.e. Date attributes, DateTime-valued profile variables, and parsed dates) are assumed to be in local time. Inputs with time zone information (i.e. TimestampOffset attributes, DateTimeOffset-valued profile variables, and parsed timestamps) are converted to local time. This means that most of the time, ArcadeExpression that produces a Date will return it as a local DateTimeOffset.

When creating dates inside Arcade expressions, be aware that Arcade’s Date() and DateOnly() functions use a zero-based index for months, where 0 represents January and 11 represents December. Putting it all together:

Arcade Expression Expected evaluation result
$feature.SomeDateField Either a UTC DateTime or a UTC DateTimeOffset depending on EnableTimestampOffsetSupport setting.
$feature.TimestampOffsetField A DateTimeOffset matching feature’s original time zone.
DateOnly(1988, 1, 5) A DateOnly representing 1988-02-05 (because months are zero-indexed).
Time() A TimeOnly with local wall time.
Date('2016-10-20T17:41:37') A DateTimeOffset interpreted as local time (17:41:37 PST).
Date('2016-10-20T17:41:37+00:00') A DateTimeOffset converted to local time (9:41:37 PST).
ToUTC(Date('2016-10-20T17:41:37+00:00')) A UTC DateTimeOffset (17:41:37 UTC).

Time and Date in Feature Forms

Feature forms support editing Date fields using DateTimePickerFormInput. Editing DateOnly, TimeOnly, and TimestampOffset fields will be supported in a future release.

Although Date fields are stored in UTC, the DateTimePickerFormInput will always display values converted to the local time zone. Keep time zones in mind when declaring Min and Max constraints for a DateTimePickerFormInput — these are absolute UTC timestamps and do not account for user’s time zone.

For example, a Date field with value “1969-07-20T20:17:00Z” will be displayed to a user in Florida as “20 July 1969, 4:17:00 PM” (EDT). If the input uses Min/Max properties to constrain values to the range “1900-01-01T00:00:00Z” to “1999-12-31T23:59:59Z”, then user will be able to pick any value between “1899-12-31 19:00:00” (EST) and “1999-12-31 18:59:59” (EST).

Conclusion

The new DateOnly, TimeOnly, and TimestampOffset field types in ArcGIS Maps SDKs for Native Apps 200.4 release provide more precise and effective ways to store and manage temporal data. You can now:

  • Represent dates and times separately when needed.
  • Store time zone-aware timestamps for mapping events across time zones.
  • Utilize these types in Arcade expressions.

We’re excited to offer this expanded functionality and hope it enhances your applications. Enabling TimestampOffset support may require some code changes, but using data types that are right for the job will make developers’ and users’ lives easier in the long term. Please share your thoughts and questions on the .NET Maps SDK’s Esri Community board.

Share this article

Subscribe
Notify of
0 Comments
Oldest
Newest
Inline Feedbacks
View all comments