File: src/main/java/org/joda/time/DateTimeZone.java
Issue: #141 Bug on withLaterOffsetAtOverlap method
The method withLaterOffsetAtOverlap created to workaround the issue 3192457 seems to not be working at all.
I won´t write many info about the problem to solve because the issue 3192457 have this info indeed.
But If something is unclear I can answer on the comments.
Problem demonstration:
TimeZone.setDefault(TimeZone.getTimeZone("America/Sao_Paulo"));
DateTimeZone.setDefault( DateTimeZone.forID("America/Sao_Paulo") );
    DateTime dtch;
    {
        dtch = new DateTime(2012,2,25,5,5,5,5).millisOfDay().withMaximumValue();
        System.out.println( dtch ); // prints: 2012-02-25T23:59:59.999-02:00 //Were are at the first 23:** of the day.
        //At this point dtch have the -03:00 offset
    }
    {
        dtch = dtch.plus(60001);
        System.out.println( dtch ); // prints: 2012-02-25T23:01:00.000-03:00 //Were are at the first minute of the second 23:** of the day. Ok its correct
        //At this point dtch have the -03:00 offset
    }
    {
        dtch = dtch.withEarlierOffsetAtOverlap();
        System.out.println( dtch ); // prints: 2012-02-25T23:01:00.000-02:00 //Were are at the first minute of the first 23:** of the day. Ok its correct
        //At this point dtch have the -02:00 offset ( because we called withEarlierOffsetAtOverlap() ) // This method is working perfectly
    }       
    {
        dtch = dtch.withLaterOffsetAtOverlap();
        System.out.println( dtch ); // prints: 2012-02-25T23:01:00.000-02:00 //Were are at the first minute of the first 23:** of the day. 
        // Here is the problem we should have a -03:00 offset here since we called withLaterOffsetAtOverlap() expecting to change to the second 23:** of the day
    }

On the last two brackets we can see that withLaterOffsetAtOverlap is not undoing withEarlierOffsetAtOverlap as it should ( and not even working at all )

Buggy code:
public long adjustOffset(long instant, boolean earlierOrLater) {
    // a bit messy, but will work in all non-pathological cases
    
    // evaluate 3 hours before and after to work out if anything is happening
    long instantBefore = convertUTCToLocal(instant - 3 * DateTimeConstants.MILLIS_PER_HOUR);
    long instantAfter = convertUTCToLocal(instant + 3 * DateTimeConstants.MILLIS_PER_HOUR);
    if (instantBefore == instantAfter) {
        return instant;  // not an overlap (less than is a gap, equal is normal case)
    }
    
    // work out range of instants that have duplicate local times
    long local = convertUTCToLocal(instant);
    return convertLocalToUTC(local, false, earlierOrLater ? instantAfter : instantBefore);
    
    // calculate result
      // currently in later offset
      // currently in earlier offset
}

Fixed code:
public long adjustOffset(long instant, boolean earlierOrLater) {
    // a bit messy, but will work in all non-pathological cases
    
    // evaluate 3 hours before and after to work out if anything is happening
    long instantBefore = instant - 3 * DateTimeConstants.MILLIS_PER_HOUR;
    long instantAfter = instant + 3 * DateTimeConstants.MILLIS_PER_HOUR;
    long offsetBefore = getOffset(instantBefore);
    long offsetAfter = getOffset(instantAfter);
    if (offsetBefore <= offsetAfter) {
        return instant;  // not an overlap (less than is a gap, equal is normal case)
    }
    
    // work out range of instants that have duplicate local times
    long diff = offsetBefore - offsetAfter;
    long transition = nextTransition(instantBefore);
    long overlapStart = transition - diff;
    long overlapEnd = transition + diff;
    if (instant < overlapStart || instant >= overlapEnd) {
      return instant;  // not an overlap
    }
    
    // calculate result
    long afterStart = instant - overlapStart;
    if (afterStart >= diff) {
      // currently in later offset
      return earlierOrLater ? instant : instant - diff;
    } else {
      // currently in earlier offset
      return earlierOrLater ? instant + diff : instant;
    }
}