I want to calculate the user online time, from the API response, by taking the first and last login time.. I tried to parse the JSON and store it in array of strings..

enter image description here

Theres UserID, Start Time, End Time, separated by ';' .. as you can see theres 3 userId (01c03a67..........) .. how do I get the start time from the first index and start time from the last index, for each userID?

enter image description here

this is the JSON Body response

{ "userDetails": [ { "userId": "01c03a67-32aa-4d3b-b0e4-02fe9d9f9599", "primaryPresence": [ { "startTime": "2018-10-04T07:34:54.223Z", "endTime": "2018-10-10T05:38:12.906Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-10T05:38:12.906Z", "endTime": "2018-10-10T05:41:21.866Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-10T05:41:21.866Z", "endTime": "2018-10-12T06:43:57.893Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" } ] }, { "userId": "4f798b1d-d27a-4415-b793-02b420586e73", "primaryPresence": [ { "startTime": "2018-10-04T11:08:13.992Z", "endTime": "2018-10-08T07:09:57.926Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-08T07:09:57.926Z", "endTime": "2018-10-09T18:03:10.752Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-09T18:03:10.752Z", "endTime": "2018-10-09T18:03:12.087Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-09T18:03:12.087Z", "endTime": "2018-10-12T09:38:38.575Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" } ] }, { "userId": "ab24ddb8-f1ef-4cca-ae72-9f20f5975332", "primaryPresence": [ { "startTime": "2018-10-04T10:31:32.224Z", "endTime": "2018-10-05T02:55:37.812Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-05T02:55:37.812Z", "endTime": "2018-10-05T03:04:27.292Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-05T03:04:27.292Z", "endTime": "2018-10-05T03:04:39.424Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-05T03:04:39.424Z", "endTime": "2018-10-05T03:19:41.220Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-05T03:19:41.220Z", "endTime": "2018-10-05T03:19:49.329Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-05T03:19:49.329Z", "endTime": "2018-10-05T03:28:23.534Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-05T03:28:23.534Z", "endTime": "2018-10-05T07:04:08.110Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-05T07:04:08.110Z", "endTime": "2018-10-05T07:06:46.264Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-05T07:06:46.264Z", "endTime": "2018-10-05T07:50:13.548Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-05T07:50:13.548Z", "endTime": "2018-10-05T07:51:24.799Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-05T07:51:24.799Z", "endTime": "2018-10-08T02:57:30.403Z", "systemPresence": "OFFLINE", "organizationPresenceId": "ccf3c10a-aa2c-4845-8e8d-f59fa48c58e5" }, { "startTime": "2018-10-08T02:57:30.403Z", "endTime": "2018-10-08T03:23:21.741Z", "systemPresence": "AVAILABLE", "organizationPresenceId": "6a3af858-942f-489d-9700-5f9bcdcdae9b" }, { "startTime": "2018-10-08T03:23:21.741Z", "endTime": "2018-10-08T03:23:43.564Z", "systemPresence": "BUSY", "organizationPresenceId": "31fe3bac-dea6-44b7-bed7-47f91660a1a0" }, { "startTime": "2018-10-08T03:23:43.564Z", "endTime": "2018-10-08T03:23:48.470Z", "systemPresence": "AWAY", "organizationPresenceId": "5e5c5c66-ea97-4e7f-ac41-6424784829f2" } ] } ] }

  • as already mentioned in your previous post Parsing Using JSON2Apex Please Refrain from adding 'I am new to...' as it is irrelevant. Thanks
    – glls
    Oct 21, 2018 at 19:15

2 Answers 2


This type of logic problem isn't really unique to JSON. Fortunately, it looks like your array is already sorted by user Id and by the time of login events. You just need to maintain some state as you iterate over these entries so that you can tell, each time through the loop, if you've switched to a different user.

I'll sketch this out in pseudocode, and you can refine the algorithm for your specific use case here. As you say, we're trying to find the difference between the earliest and latest login dates for each user.

public static Map<String, Integer> parseLoginEvents(List<String> inputData) {
    // First, create a Map<String, Integer> where the keys are user Ids 
    // and the values are the date differences.
    Map<String, Integer> returnValue = new Map<String, Integer>();

    // Now, declare our state variables that we'll use to check where we are each time we iterate through the loop.
    String processingUserId;
    DateTime firstLoginTime;
    DateTime previousEntryLoginTime;

    // Now, loop through the input data.
    for (String entry : inputData) {
        // Implementing these functions below is left as an exercise.
        String user = getUserForEntry(entry);
        DateTime loginTime = getLoginTimeForEntry(entry);

        // Now, determine whether we're changing to look at a different user or not.
        if (processingUserId != user) {
            if (processingUserId != null) {
                // We just finished processing one user
                // And we know this because the current loop iteration has
                // a different Id
                returnValue.put(processingUserId, firstLoginTime - previousEntryLoginTime);
            // Reset our context variables. Note that this also
            // handles the case where we just started processing
            // the first user.
            processingUserId = user;
            firstLoginTime = loginTime;
        // Save this entry's login time in case the *next* entry changes
        // user, since we'd need to do the calculation at that point.
        previousEntryLoginTime = loginTime;

    // Lastly, we have to handle closing out the final user in the list
    returnValue.put(processingUserId, firstLoginTime - previousEntryLoginTime);

    return returnValue;

This is pretty rough, but it's meant as an example of how you can implement this type of logic - where you're adding more structure to a flat list of data items. You'll often have to maintain state across loop iterations in this type of fashion, and include logic to make sure you handle the start and end of the list appropriately.

There are other ways you could execute this, of course. You could, for example, create a wrapper class to represent each log entry, preprocess the data into a Map<String, List<WrapperClass>> where each key is a user Id and the associated List contains each of their login entries, sort the lists (your wrapper class would need to implement Comparable), and then just check the first and last list entries.

Fundamentally, though, it's a logic challenge - not specifically a JSON or Apex challenge. Once you pick the logical structure that works for your application, then you've just got to find the right idioms in Apex to implement it effectively.


If this is a follow-on to Learn Parsing JSON, then based on that JSON it is these values:

"interval": "2018-10-01T01:00:00.000Z/2018-10-07T01:00:00.000Z"

that you would need this sort of code to parse each one of:

String s = '2018-10-01T01:0:00.000Z/2018-10-07T01:00:00.000Z';
String[] parts = s.split('/');
DateTime dt0 = (DateTime) JSON.deserialize('"' + parts[0] + '"', DateTime.class);
DateTime dt1 = (DateTime) JSON.deserialize('"' + parts[1] + '"', DateTime.class);
System.debug('>>> ' + dt0 + ' ' + dt1);

Note that in my original answer to Learn Parsing JSON, I was only putting the data into a string to demonstrate that the parsing was working. The parser has the data correctly split up already, so you should grab and process the various pieces directly into your final data structure.

  • this is different JSON body response.. hmm let me try 1st.. thanks again Keith Oct 21, 2018 at 19:02
  • @AriefGunawanTjiptorahardja Ah I see. You will probably still need to use the JSON.deserialize technique to parse the DateTime values,
    – Keith C
    Oct 21, 2018 at 19:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .