It's worth noting that you can create this trigger functionality without writing a single line of code if you just install the Declarative Lookup Rollup Summaries tool and configure the corresponding
Lookup Rollup Summary.
The closest constructor which would be valid is to use
new Map<Id, SObject>(List<SObject>). That would look like:
Map<Id, Event> events = new Map<Id, Event>([/*query*/]);
This constructor will map each record by its own Id. If you want to map each
AccountId to the corresponding
EndDateTime, you will have to roll your own map. Note that there can be multiple records matching the same key, so you have to decide whether you want to just clobber the results, get the most recent value, etc.
A typical pattern for doing the mapping yourself would be:
Map<Id, List<Datetime>> times = new Map<Id, List<Datetime>>();
for (Event record : [/*query*/])
times.put(record.AccountId, new List<Datetime>());
You could also use a clever aliasing trick to, for example, get the most recent timestamp for each
Map<Id, AggregateResult> mostRecent = new Map<Id, AggregateResult>([
SELECT AccountId Id, MAX(EndDateTime) EndDateTime FROM Event
With this map in hand, you will consume much less CPU time getting the data you need. Note also that you do not need to query for a record to update it. If you already know its Id, you can just construct a record with that Id and you're good to go.
List<Account> accounts = new List<Account>();
for (Id accountId : mostRecent.keySet())
If you get a chance, you should look at best practices around error handling and logic-less trigger bodies (using a trigger handler pattern).