Skip To Content

Viewing Temporal data

In this topic

Geographic data that is sometimes temporal in nature. Temporal data represents the state of an entity under observation at a particular time instant, or over a time period. For example, the progression of a hurricane, changes in sea temperature, destruction of wildlife habitat, or the spread of disease. By viewing and analyzing these changes in temporal sequence, you can easily identify trends and spot patterns in the data that would have otherwise not been noticed.

Learn more about Temporal data

A map allows you to visualize temporal data and filter out data that does not belong to a specific time period. When used in conjunction with a temporal renderer, you can easily symbolize changes that take place over time.

Time-aware Layers

The map must contain at least one time-aware layer to be able to display temporal data. The following types of layers can be time-aware : ArcGIS Server Dynamic Map Service Layer, ArcGIS Image Service Layer, and ArcGIS Feature Layer. A layer is time aware if the service it is using contains time-enabled data.

Learn more about enabling time on your data

You can easily tell if a service contains time-enabled data by using the ArcGIS Services Directory. If the Time Info property is listed it means the data is time-enabled.

Time Info in Services Directory
Time information in ArcGIS Services Directory for a time-enabled service

You can also programmatically check whether a layer is time-aware or not by inspecting its timeAware property.

Time Extent

Once you have at least one time-aware layer in the map, you can adjust the map's time extent to visualize the temporal data. The time extent defines the time period for which time-aware layers display their data. Setting the map's time extent is similar to setting the spatial extent. While the spatial extent specifies the geographic area to display, the time extent specifies the time period from which the data should be displayed. Whenever the map's time extent is changed, all time-aware layers update to reflect the new extent. There is no change to layers that are not time-aware.

Viewing data of a time period

The map allows you to display data that belongs to a time period. For example, displaying the earthquakes that occurred between December 3, 2001 and March 17, 2002. To accomplish this, you need create an AGSTimeExtent specifying the starting and ending points in time. You then need to set it as the map's time extent as follows -

let dec3:NSDate = ...  
let mar17:NSDate = ... 
let extent = AGSTimeExtent(start: dec3, end: mar17) 
map.timeExtent = extent
If you want to display data starting from a particular time up till the end, you can just specify the starting time and leave the ending time as nil. The following extent represent a time period from March 17, 2002 and onwards -
let mar17:NSDate = ...  
let mar17_onwards = AGSTimeExtent(start: mar17, end: nil)
Conversely, if you want to display data starting from the beginning up till a particular time, you can just specify the ending time and leave the starting time as nil. The following time extent represents a time period up till Dec 3, 2001 -
let dec3:NSDate = ...  
let till_dec3 = AGSTimeExtent(start: nil, end: dec3)
Note:

The starting and ending times on the map extent are both inclusive

Viewing data at a time instant

The map also allows you to display data that belongs to a specific time instant. For example, displaying the location of hurricane Katrina on August 25, 2005 at 6:30 AM EST. To display data belonging to a time instant, you need create an AGSTimeExtent using the same starting and ending point in time. You then need to set it as the map's time extent as follows -

let aug25_630AM:NSDate = ...  
let instant = AGSTimeExtent(start: aug25_630AM, end: aug25_630AM)

Layer time options

Time Offset

If you have two or more time-aware layers in the map, it is possible that they could be using data belonging to different time zones, or even entirely different time periods. For example, one layer could contain hourly traffic data for California in Pacific Standard Time, and the other for New York in Eastern Standard Time. One layer may contain monthly data for the Arctic ice sheet in 2001, and the other for 2011. Even when you have such data, you may want to visualize them on a map simultaneously to compare and contrast trends. For instance, you may want to compare the rush hour traffic at 5 PM PST in California with the traffic at 5 PM EST in New York, or the condition of the ice sheet in June 2001 with the condition in June 2011.

To accomplish this, you can adjust one of the layer's time options by specifying an offset. Suppose we specify an offset of +10 years to the layer containing data for the ice sheet in 2001. This will enable the layer to treat its data as belonging to 2011 instead of 2001. The actual data is not changed, the offset it applied on-the-fly. Now, when we set the map's time extent to June 2011, both layers will draw their data. The layer for the 2011 data will draw its June data as normal. But the layer for the 2001 data will first apply an offset of +10 years to its data and consequently draws its June 2001 data as if it were June 2011. Thus we can visualize the data from both layers simultaneously even though the data belonged to completely different time periods.

//Layer using the service which contains the ice sheet data from 2001
let june2001Layer:AGSDynamicMapServiceLayer = ...;
        
let op = AGSLayerTimeOptions()
op.layerId = 1 //id of the sub-layer containing the actual data
op.timeOffset = 10
op.timeOffsetUnits = .Years
        
//Set the layer time options
june2001Layer.layerTimeOptions = [op]

Cumulative Time

As described earlier, you can use a time extent containing only an ending time to display temporal data cumulatively up till the ending point of the time extent. However, there may be cases when you have more than one time-aware layers in the map, but you only want to display temporal data cumulatively for some of them. In such cases, it wouldn't be feasible to use a cumulative time extent with the map as it would force all the time-aware layers to display data cumulatively.

To handle such cases, you can modify the time options of individual layers to always display temporal data cumulatively. This will allow you to use time extents that have well defined starting and ending points, but the chosen layers will still display temporal data cumulatively up till and including the specified time extent.

let op = AGSLayerTimeOptions()
op.layerId = 1 //id of the sub-layer containing the actual data
op.timeDataCumulative = true

Disable Time

You can also temporarily exclude time-aware layers from honoring the map's time extent by disabling their time option. These layers will then behave as if they were not time aware and simply display all their data.

let op = AGSLayerTimeOptions()
op.layerId = 1 //id of the sub-layer containing the actual data
op.useTime = false

Creating NSDate objects

When querying or viewing with temporal data, you will often have to create NSDate objects to specify a time extent. When you create NSDate objects, they use the timezone of the application by default. On a device, the timezone could either be based on the time information provided by the cellular network provider, or could have been set manually through Settings. There may be times when the timezone being used by the application may be different from the timezone being used by the service's data. This could lead to some subtle problems.

To illustrate one such problem, suppose that a service contained temporal data tracking the historic progression of hurricanes on an hourly basis. Also suppose that the data is stored in GMT. You want to display the location of active hurricanes at a particular time, say 1 Jan 2000, 12 AM GMT, so you create an AGSTimeExtent with the corresponding NSDate objects.

//Covert from string to data using formatter
let inputFormatter = NSDateFormatter()
inputFormatter.dateFormat = "M/d/yyyy h:mm a"
        
//We want 12 AM GMT, but this will return 12 AM in the application's timezone
let date = inputFormatter.dateFromString("1/1/2001 12:00 AM")
        
let extent = AGSTimeExtent(start: date, end: date)

If the application was using a different time zone by default, say Pacific Standard Time, you would actually end up with an NSDate representing 1 Jan 2000, 12 AM PST instead of 12 AM GMT. As a result, the layer would display active hurricanes for 1 Jan 2000, 12 AM PST which is equivalent to 1 Jan 2000, 8 AM GMT, even though we originally set out display features of 12 AM GMT.

To solve such problems, you should specify a timezone for the time values that you use. The iOS platform will then automatically adjust the time values, if needed, to create an equivalent NSDate object using your application's default time zone. In the following example, we specify a value of 12 AM, but also indicate that the value belongs to GMT -

let inputFormatter = NSDateFormatter()
inputFormatter.dateFormat = "M/d/yyyy h:mm a"
        
//specify the time zone that the value belongs to
inputFormatter.timeZone = NSTimeZone(name: "GMT")
        
let date = inputFormatter.dateFromString(@"1/1/2001 12:00 AM")

See Also