Q:

Detecting if the player is underwater

I am in Java 1.14.4 and I'm trying to create an item that gives the player water_breathing if they are underwater, but I can't find a good way to detect if the player is fully underwater. 
execute as @a at @s if block ~ ~1.6 ~ water

Problem with this command is that there could be some other block above the player's head.  There also doesn't seem to be any NBT data the player has to simply test for this. 
scoreboard objectives add inWater minecraft.custom:minecraft.walk_under_water_one_cm

Doesn't work either since the player must actually be walking for this to occur.  

A:

It's fairly straightfoward to do this by exploiting the fact that, when a player is underwater, their air meter will begin decreasing, which can be measured by command blocks.
First, set up the necessary scoreboard objectives (running these commands once):
/scoreboard objectives add air air
/scoreboard objectives add difference dummy

Then, every tick, run these command blocks in order (using a repeating command block and a chain command block):
/execute as @a run scoreboard players operation @s difference -= @s air
<command goes here>
/execute as @a run scoreboard players operation @s difference = @s air

Between the two /execute commands, you can select underwater players using the selector @a[scores={difference=1..}].
This isn't 100% reliable for a few reasons, but it should work:

It fails to detect players who are underwater with a water breathing effect (which doesn't matter at all if what your command does is give players water breathing). You can detect players who gained the water breathing effect while underwater (but not players who had water breathing beforehand) with @a[scores={difference=0..},nbt=!{Air:300s}].
It fails to detect players the exact tick they take damage from drowning.

