Use the Minkowski sum
A good way to solve this problem is to consider the intersection between a line of motion (v) translated to the origin (v') and the Minkowski sum of A rotated 180 degrees at the origin (A') and its obstacles (just B in this case): A' ⊕ B.
In the following picture I place A smack-dab in the origin of an arbitrary coordinate system. This simplifies understanding as rotating A by 180 degrees results in A', and v translated to the origin equals v'.
The Minkowski sum is the green rectangle, and the intersection points of a moving A and a stationary B can be found by doing line-AABB intersection. These points are marked with the blue circles.

In the following picture a different origin was used and the same intersection points are found.

Multiple moving AABBs
To make this work for two AABBs that move in a linear fashion during a specific period of time you would subtract B's velocity vector from A's velocity vector and use that as the line segment for the line-AABB intersection.
Pseudo code
def normalize(aabb):
return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),
def rotate_about_origin(aabb):
return normalize({x1: -aabb.x1, x2: -aabb.x2
y1: -aabb.y1, y2: -aabb.y2})
# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}
def get_line_segment_from_origin(v):
return {x1: 0, y1: 0, x2: v.x, y2: v.y}
def moving_objects_with_aabb_intersection(object1, object2):
A = object1.get_aabb()
B = object2.get_aabb()
# get A'⊕B
rotated_A = rotate_about_origin(A)
sum_aabb = minkowski_sum(rotated_A, B)
# get v'
total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
line_segment = get_line_segment_from_origin(total_relative_velocity)
# call your favorite line clipping algorithm
return line_aabb_intersection(line_segment, sum_aabb)
Collision response
Depending on the gameplay you would either perform more fine-grained collision detection (maybe the AABB's contain meshes), or move forward to the next phase: collision response.
When there is a collision the line-AABB-intersection algorithm will return either 1 or 2 intersection points depending on whether A ends its movement inside B or passes through it, respectively. (This is discounting the degenerate cases where A grazes B along their sides or along one of their respective corners.)
Either way, the first intersection point along the line segment is the collision point, you'd translate this back to the correct position in the world coordinate system (the first light-blue circle in the second picture along the original v, call it p) and then decide (e.g., for elastic collisions by reflecting v along the collision normal at p) what the actual position for A at the end of the frame will be (At+1).

If there are more than just 2 colliders this will get a little more complex, as you'd want to do collision detection for the second, reflected, part of v as well.