ICU-20919 Merge maint/maint-66 (release-66-preview) to master

diff --git a/.cpyskip.txt b/.cpyskip.txt
index fc8af8a..878546e 100644
--- a/.cpyskip.txt
+++ b/.cpyskip.txt
@@ -16,6 +16,8 @@
 .travis.yml
 .appveyor.yml
 .ci-builds/*
+# PGP Keys
+KEYS
 # suffix matches - start with '*'.  They are turned into as RE, '.brk$'
 *.brk
 *.bz2
diff --git a/KEYS b/KEYS
new file mode 100644
index 0000000..6af2eb7
--- /dev/null
+++ b/KEYS
@@ -0,0 +1,817 @@
+This file contains the PGP keys of ICU developers.
+Compare to http://www.apache.org/dist/ant/KEYS and read https://www.apache.org/dev/openpgp.html for background
+
+To import these keys:
+   gpg --import KEYS
+
+To update this file:
+replace $KEYID is your key's ID:
+  (gpg --list-sigs  $KEYID && gpg --armor --export $KEYID ) >> KEYS
+
+
+pub   2048R/825EA2CD 2010-11-02
+uid                  ICU Project @IBM (International Components for Unicode Development at IBM) <icuintl@us.ibm.com>
+sig 3        825EA2CD 2010-11-02  ICU Project @IBM (International Components for Unicode Development at IBM) <icuintl@us.ibm.com>
+sig 3        FD8FABF1 2013-12-12  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+sig          0F0DE47D 2014-09-17  Steven R. Loomis (CODE SIGNING KEY) <srl@icu-project.org>
+sub   2048R/1D06B1BF 2010-11-02
+sig          825EA2CD 2010-11-02  ICU Project @IBM (International Components for Unicode Development at IBM) <icuintl@us.ibm.com>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.14 (GNU/Linux)
+
+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
+AZA1XWLRgZ3+5+vD
+=NkHr
+-----END PGP PUBLIC KEY BLOCK-----
+
+
+pub   4096R/0F0DE47D 2014-09-17 [expires: 2019-09-16]
+uid                  Steven R. Loomis (CODE SIGNING KEY) <srl@icu-project.org>
+sig 3        0F0DE47D 2014-09-17  Steven R. Loomis (CODE SIGNING KEY) <srl@icu-project.org>
+sig          FD8FABF1 2014-09-17  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.14 (GNU/Linux)
+
+mQINBFQZ3doBEACpnA2AbRRVxu9TeDTnjHtz6h5NyMyGZIPZOX7Iv2bNS0JSAS/H
+9f2WP9+3ANHuKI32rYh0snKpWjYsgUCxZ8x2Wp4cu8YnTvvpL6a5fn5n04dTyd4s
+/gPLb51qHIL8L6MDfK2ARgukntzfLR2CoL+RwGLDOjNlnoGNw65XEdjkzZ65s05Q
+/YHdlMYJE6gQ7VzJf7JYO6z6MpclLSj106TDs0hmOSetRm66nt+G7q1iY/jMXSMm
+bs3CFe4MNoVlRnl2THFZWjGSrVNYkenKexrjJ5HD9sm2nFF5pXgMQBoyOE5gic/b
+H5hMeh3v4vmhxRL5GPmI9Ir25LwqYCaWZDu6TC8mDDJj82YQMOzvElpRU/5V8KVc
+R7e4FN7D6tXDPb8IMgHb1U7zEnKYAc+uAS5NQ6Vq/S3NoueEQNk+rwqy44yIigtD
+iOJOnLvf1JFUPNFUxRu2JUy7YzvvcyGG9PY7bxQEb/MLwa424GWRTHV4Yw+hHP6D
++XgylCyd36wfwgF48+gFeDza9gMPPDgGqJu059PjEEG9ELgBFkTVjM0+rqq1M6Jk
++WPFRgM9ioccwdVIvfVZNnkp+EUjpl/PHLYlFvP0orkK3SGc1jaqW5m3Y6P60RzM
+7OovZqtqUDTEfMZ4bQKT4EdLayBPFALvz4TgndxrZwoPi2QGmFU9Dy+snwARAQAB
+tDlTdGV2ZW4gUi4gTG9vbWlzIChDT0RFIFNJR05JTkcgS0VZKSA8c3JsQGljdS1w
+cm9qZWN0Lm9yZz6JAj4EEwECACgFAlQZ3doCGwMFCQlmAYAGCwkIBwMCBhUIAgkK
+CwQWAgMBAh4BAheAAAoJEKqprpwPDeR9St0P/RJzlQDOgtD/rq8ThV5clhcgzCQU
+J34bC9+SdvQVtG6cOu+/mE9fjPcRuMSC2saj3e6KdfdCF51ZUelFgg7Nf4VjzKXK
+egYFe11CJSYFt0YQyT3CwlX5a6lKv9BH4RJPdAjeACSNCLvuZYlkxfAFPAwJFMAH
+CeiY6P7Llm2sHHIIubK+yFviZiD1ic92ADt2llM06VwniCS2Cs0kx4NAl70jd/vW
+B/j9+k+PphZFA2IUuB80qnTdrEb+nVLQ9n0SMFwFm89bEm8IhXe0Lb//jl5ZbZCr
+afn02GvdSqU73jqOfEHS7hHemB1KSM4hEdWGFRhUf0+Xpc31aOsnKY5Wu89A8Sz/
+sKp554qAhGmBGeEjkKbw0t+k4liP+LW2efmVBt+/6msF+TGq0Rr5vFQEUNCYeIzz
+DS5nKDlKvRwgx/41RnSUYiLJS9GkCB6skxIQZvW2G7rnkGQkgmP3/tkTTX0EP0rT
+GlW4ivfp+AKoYozkZ5FNLXC06yzCSKYL0z9uoL38uR6opXo4768byzzkBOvSut3Q
+V9gbvAtZvwEibwOt0A4UhbIyv96+Oi2WI66q37Wl33F/QIsxpC9UjXju1RrAajOv
+0gY8VMxwuWHN8ewslykX5rohxgA7mkTf/YeELSiYEM1WpmKmj30uJapgDwVRpsTC
+dfSvIc/nOLji4u0iiQEcBBABAgAGBQJUGfLZAAoJEKyl2+H9j6vx+58IAMIzjJTv
+9n7Yq2iyncFyg7fmPmlKo28l6cIrmveGtzLWgO7pXw9hZy8mTwUAhg9nMnNbnjDw
+qSA+YH8rNy0MB/AaTj46faE/RlqB8bCUlnLlRk9b6IxKODOVAarFk0ltCUeNt1IP
+w8YziwUaJewmb2//tEjwG4RuliQeo8EPcg2MejsxctNJ1gWQxZFOSMk2M6I9NwW6
+xMUmqGzzKdPChdwzOBaHK2f4lB3IlPqpJVqAWuXdINzi91tCIKfo508hJSpzGm/n
+Lq4yQHJPjQjxTldFBxC8Ji5yYIQ2ZcWLaYndWH4aVbAkEelU3eIp44mU4tqhqCP6
+zJJjdh87G81yUoE=
+=pu4w
+-----END PGP PUBLIC KEY BLOCK-----
+pub   2048R/FD8FABF1 2013-12-12 [expires: 2020-10-03]
+uid                  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+sig 3        FD8FABF1 2017-10-04  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+uid                  [jpeg image of size 10375]
+sig 3        FD8FABF1 2017-10-04  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+sig 3        FD8FABF1 2013-12-12  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+sig 3        FD8FABF1 2013-12-12  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+sub   2048R/A6EB1469 2013-12-12 [expires: 2019-10-04]
+sig          FD8FABF1 2017-10-04  Steven R. Loomis (ICU Project) <srl@icu-project.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBFKpD3cBCADklZIzuPsYrEy08rASB+MRnFF8hqDDUkDHuvS0bJwEDge2EEHT
+l9rnUOt3SGtSrokeniQbwut26vuY/V59SSpwClytbHovIRJ/ovjq3nUasCRPOxDL
+mlmftkRGrO6WYH6hSzmRy2x3NTgQOlE/YRtOya3CAVlkiybpYXL3L1mJA4e80NpF
+V4UG7vyfw44OHFeO6mInqkcxVgKkxwp3wBbck3FEySEZT0DTT+sQHI52fgUftb+P
+xBH1s58lLAub4o2z1hnImPN/BR0lZpiNj59vzNlqmcnRHTpa6KIz+Qeep9dwLL7i
+71lMfCsEgVyDZxkQxFpNoRYRHRkfvBEY7JLpABEBAAG0NFN0ZXZlbiBSLiBMb29t
+aXMgKElDVSBQcm9qZWN0KSA8c3JsQGljdS1wcm9qZWN0Lm9yZz6JAT4EEwECACgC
+GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJZ1XNBBQkMz/5KAAoJEKyl2+H9
+j6vxKIEH/0aFGlFOtgXNHKEG7F1mVxhjNyFlZD5O/9t8oI46vYCgVfwsn6BsHFpv
+9yAtzA6z26Zt2NsPjH6dVRfc3sGCojBIKQ/lxnyQqjAYaEbVVQ/3jhAhgnm+uAF4
+3Rr54g+6FL7aHB33nDy9FmRtmQsyVf1OySR7VXbHpwEVzWeLrgmPKR1t8P1hdiSo
+YfroXVAPy2pynXUWgWbMbuqAcTj0iAQQ7LuVOVZ8bYA922LRgUxg/ZPxiGGm2g3M
+LF/QVWMH6FAHtSf9DOaFjZqQuypkUoOZZuFfNMvKaYIe+XviZRtWls5M6H8wOz6c
+bFrLBV5XBBwKbOXULpDv/3+oehDO22vR/wAAKJ3/AAAomAEQAAEBAAAAAAAAAAAA
+AAAA/9j/4AAQSkZJRgABAQEASABIAAD/4hscSUNDX1BST0ZJTEUAAQEAABsMYXBw
+bAIQAABtbnRyUkdCIFhZWiAH3QALAAUADwAzADFhY3NwQVBQTAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFkZXNjAAABUAAAAGJkc2NtAAAB
+tAAABA5jcHJ0AAAFxAAAACN3dHB0AAAF6AAAABRyWFlaAAAF/AAAABRnWFlaAAAG
+EAAAABRiWFlaAAAGJAAAABRyVFJDAAAGOAAACAxhYXJnAAAORAAAACB2Y2d0AAAO
+ZAAABhJuZGluAAAUeAAABj5jaGFkAAAauAAAACxtbW9kAAAa5AAAAChiVFJDAAAG
+OAAACAxnVFJDAAAGOAAACAxhYWJnAAAORAAAACBhYWdnAAAORAAAACBkZXNjAAAA
+AAAAAAhEaXNwbGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbWx1
+YwAAAAAAAAAhAAAADGhySFIAAAAUAAABnGtvS1IAAAAMAAABsG5iTk8AAAASAAAB
+vGlkAAAAAAASAAABzmh1SFUAAAAUAAAB4GNzQ1oAAAAWAAAB9GRhREsAAAAcAAAC
+CnVrVUEAAAAcAAACJmFyAAAAAAAUAAACQml0SVQAAAAUAAACVnJvUk8AAAASAAAC
+am5sTkwAAAAWAAACfGhlSUwAAAAWAAACkmVzRVMAAAASAAACamZpRkkAAAAQAAAC
+qHpoVFcAAAAMAAACuHZpVk4AAAAOAAACxHNrU0sAAAAWAAAC0npoQ04AAAAMAAAC
+uHJ1UlUAAAAkAAAC6GZyRlIAAAAWAAADDG1zAAAAAAASAAADImNhRVMAAAAYAAAD
+NHRoVEgAAAAMAAADTGRlREUAAAAQAAADWGVuVVMAAAASAAADaHB0QlIAAAAYAAAD
+enBsUEwAAAASAAADkmVsR1IAAAAiAAADpHN2U0UAAAAQAAADxnRyVFIAAAAUAAAD
+1mphSlAAAAAOAAAD6nB0UFQAAAAWAAAD+ABMAEMARAAgAHUAIABiAG8AagBpzuy3
+7AAgAEwAQwBEAEYAYQByAGcAZQAtAEwAQwBEAEwAQwBEACAAVwBhAHIAbgBhAFMA
+egDtAG4AZQBzACAATABDAEQAQgBhAHIAZQB2AG4A/QAgAEwAQwBEAEwAQwBEAC0A
+ZgBhAHIAdgBlAHMAawDmAHIAbQQaBD4EOwRMBD4EQAQ+BDIEOAQ5ACAATABDAEQg
+DwBMAEMARAAgBkUGRAZIBkYGKQBMAEMARAAgAGMAbwBsAG8AcgBpAEwAQwBEACAA
+YwBvAGwAbwByAEsAbABlAHUAcgBlAG4ALQBMAEMARCAPAEwAQwBEACAF5gXRBeIF
+1QXgBdkAVgDkAHIAaQAtAEwAQwBEX2mCcgAgAEwAQwBEAEwAQwBEACAATQDgAHUA
+RgBhAHIAZQBiAG4A6QAgAEwAQwBEBCYEMgQ1BEIEPQQ+BDkAIAQWBBoALQQ0BDgE
+QQQ/BDsENQQ5AEwAQwBEACAAYwBvAHUAbABlAHUAcgBXAGEAcgBuAGEAIABMAEMA
+RABMAEMARAAgAGUAbgAgAGMAbwBsAG8AcgBMAEMARAAgDioONQBGAGEAcgBiAC0A
+TABDAEQAQwBvAGwAbwByACAATABDAEQATABDAEQAIABDAG8AbABvAHIAaQBkAG8A
+SwBvAGwAbwByACAATABDAEQDiAOzA8cDwQPJA7wDtwAgA78DuAPMA70DtwAgAEwA
+QwBEAEYA5AByAGcALQBMAEMARABSAGUAbgBrAGwAaQAgAEwAQwBEMKsw6TD8ACAA
+TABDAEQATABDAEQAIABhACAAQwBvAHIAZQBzAAB0ZXh0AAAAAENvcHlyaWdodCBB
+cHBsZSBJbmMuLCAyMDEzAABYWVogAAAAAAAA81IAAQAAAAEWz1hZWiAAAAAAAABq
+egAAPKoAAAYFWFlaIAAAAAAAAGhwAACq+AAAH7dYWVogAAAAAAAAI+wAABheAACt
+cWN1cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANgA7AEAARQBKAE8A
+VABZAF4AYwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCjAKgArQCyALcAvADBAMYA
+ywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIB
+WQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwC
+FAIdAiYCLwI4AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUD
+AAMLAxYDIQMtAzgDQwNPA1oDZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBME
+IAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcF
+dwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkGagZ7BowGnQavBsAG0QbjBvUH
+BwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgyCEYIWghuCIIIlgiqCL4I
+0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK
+3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0N
+Jg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96D5YP
+sw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcSJhJFEmQS
+hBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVWFXgV
+mxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY
++hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHsc
+oxzMHPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwg
+mCDEIPAhHCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk
+2iUJJTglaCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgp
+aymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYu
+TC6CLrcu7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0Yz
+fzO4M/E0KzRlNJ402DUTNU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5
+BTlCOX85vDn5OjY6dDqyOu87LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+
+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5F
+EkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NL
+mkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP3VAnUHFQu1EGUVBRm1HmUjFS
+fFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX4FgvWH1Yy1kaWWlZ
+uFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9fYV+zYAVgV2CqYPxh
+T2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+loP2iWaOxp
+Q2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDgcTpx
+lXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6
+RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSD
+V4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOM
+yo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSW
+n5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg
+2KFHobaiJqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKr
+davprFys0K1ErbiuLa6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2
+ebbwt2i34LhZuNG5SrnCuju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB
+48JfwtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXN
+tc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ
+8dp22vvbgNwF3IrdEN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3m
+lucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnz
+p/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8B/yY/Sn9uv5L/tz/bf//cGFy
+YQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACg52Y2d0AAAAAAAAAAAAAwEAAAIA
+AAAIACQAVwCkAQYBRgGTAe8CTAK0AycDoAQnBLoFWAYABrUHeAhGCRsJ+ArhC9IM
+zg3RDxQQaBG8ExkUdhXZF0kYuBotG6YdKx6vIDghyiNgJPomkygwKdUrZSzsLnUv
+9zF5Mvk0bzXjN084sToMO2M8tD3+P0VAhUHFQvlEHkVFRmpHkUi2SdxLAUwmTUlO
+bU+PULFR01L2VBlVPFZSV2pYf1mWWq1bw1zZXe5fAmAWYSliPGNOZGFldGaBZ4Bo
+gmmDaoRrhmyJbYpujG+OcJFxk3KVc5d0m3WVdnJ3UHgteQt56nrIe6Z8hn1nfkh/
+KoANgPGB1oK7g5+EhYVxhmOHX4hniXuKoYvXjR2Ob4/PkTySkJOylNaV+JcbmECZ
+ZpqOm7mc6Z4cn1KgjaHKovikDqUmpj+nWah3qZiqvKvlrRKuQ694sLGx67MftFC1
+frart9W4/boku0q8b72Vvr2/5cEPwjbDUcRhxWPGVsc7yBLI3MmbylXLDcvFzILN
+Rs4Rzt/PrdB80UrSGdLn07PUf9VJ1hLW2teZ2FHZBtm82nTbLtvo3KXdYt4h3uDf
+n+Bf4R/h3+Kc41bkDuTD5XPmIObL53LoGOi86WTqD+rC63XsKOzd7ZLuSO7/77jw
+c/Ev8ezywfOp9JL1dvZa9z/4Kvkf+iP7QvyG/gv//wAAAAcAHgBKAIsA4wEqAW4B
+wAIZAnQC2gNHA70EQQTSBW0GEQa9B3QINgkACdUKrQuODIENlg7MEAARPBJ6E7oV
+AxZPF6MY+BpUG7QdGh6GH/IhZCLWJE0lxycvKJMp9ytXLLMuCy9gMLAx+DM8NHc1
+rTbeOAo5MDpWO3c8kD2dPqw/ukDKQdlC6UP5RQpGGkcqSD1JTkpgS3FMg02UTp5P
+qVCyUbtSxlPQVNlV4lbqV/NY+1oDWwtcFF0dXiFfIWAfYR1iG2MZZBZlE2YPZwpo
+BWkAaftq9WvwbOdt2G7Ib7ZwpHGQcntzZHRLdTF2Fnb6d954wnmmeod7Z3xKfS5+
+FX8Cf/OA6oHpgvCD/YUShi2HTYhuiYuKp4vEjOKOAY8hkEORZpKNk7WU4JYNlzyY
+ZZmHmqqbzJzxnhefP6BpoZaixqP5pS6mZqegqNqqFKtOrIatvq72sCyxZLKbs9W1
+D7ZLt4m4x7oBuzq8cL2jvtG/+cEbwjbDTMRcxWnGcsdtyFrJQ8oryxPL+8zizcjO
+rs+T0HjRXtJD0yTUAdTd1bnWlNdv2ErZJdn/2tnbstyM3WbeQN8b3/fg1OGx4o3j
+auRH5STmAebd57nolOlp6j3rEevl7Lvtku5q70TwIPD98dzyu/Oc9I71lPas99X5
+C/pG+3n8mf2c/oD/Sf//AAAABQAWADUAZACkAPUBLQFqAbACAAJTArADFgOBA/UE
+cAT1BYMGHAa+B2UIEwjGCX4KQwsqDCYNJg4lDy4QNxFHElcTbhSGFaUWxxfxGRka
+SBt5HK0d4x8bIEQhaiKNI7Ak0yXwJwsoISk1KkArSCxKLUcuQS82MCoxHDIGMukz
+yTSqNY02bzdQODM5FDn1Otc7uDyaPXw+Xj9AQCJBBUHpQs5Ds0SYRX5GY0dISCxJ
+EEn1StlLvEyhTYZOaU9IUCdRBlHlUsRTolSBVV5WO1cZV/ZY01mvWo1baVxCXRtd
+817MX6Rge2FSYihi/mPTZKllfmZTZyhn+mjLaZxqbWs9bA1s3G2rbnlvRXAScN5x
+qXJ1cztz/3TBdYN2Q3cCd794e3kyeed6m3tKe/h8rH1xflp/R4A0gSKCEIL/g+2E
+2oXHhrOHnYiIiXCKaotpjGiNaI5pj2mQaJFmkmKTXZRVlUyWQZdEmFOZZ5p7m5Gc
+pp26ns2f3aDrofejAKQHpR6mU6ePqMyqC6tNrJGt2q8osHmxzrMntIO13LckuGi5
+prrcvAu9Mr5Sv2zAgMGRwp/DrcS4xcLGy8fWyOLJ78r+zA/NI846z1PQb9GN0rLT
+2dUB1irXU9h92ana1twF3TXeZ9+b4O/iheQo5d/nv+nQ7CHuuPGn9N/4XPwV//8A
+AG5kaW4AAAAAAAAGNgAAmj0AAFllAABRRwAAjYQAACXWAAAXCgAAUA0AAFQ5AAKK
+PQACRR4AAYzMAAMBAAACAAAACwAiAD0AWgB3AJUAswDRAPABEAEwAVEBcgGUAa8B
+ywHoAgYCJAJDAmMCgwKjAsQC5gMIAysDTgNxA5UDugPfBAQEKgRQBHcEngTGBO8F
+GAVBBWsFmAXHBfYGJgZXBooGvQbyBycHXweXB9IIDghMCI0IzwkTCVkJoQnsCjgK
+hwrXCykLgQveDDsMmgz6DVwNwA4lDowO9Q9gD8wQOhCqERwRjxIEEnoS8hNyE/IU
+dRT5FX8WBxaRFx0XrBg8GM8ZZBn7GpQbLxvLHGwdGR3GHnYfKB/cIJEhSiIEIsAj
+fiQ/JQIlxyaNJ1koRyk3KisrISwaLRYuFC8TMBUxGDIdMyM0LDU6Nkc3UThWOVI6
+RTsvPA885j22PoA/RkAIQMVBgEJRQ0JEM0UnRh1HE0gLSQNJ+0rzS+lM303UTshP
+u1CuUaZSwFPaVPVWEVctWEhZYlp7W5JcqF27Xs5f32DwYgBjFmQzZVJmdmecaMdp
+9WsmbFptkW7JcANxPXJ5c7R08HY6d5F4+np5fBR90H+2gcGD5YYNiCqKLYwnjiSQ
+JJIolDKWQ5hbmn2cpp7voV6jzKY4qKKrCq1yr9yySbS5ty65sLxFvvHBt8SXx43K
+lM2L0F/TN9YQ2Orbwt6W4WjkOOa26PrrVO258B7yevTC9uv46fq6/Fj9uv7p//8A
+AAANACcARgBnAIcAqADKAOwBDwEyAVcBfAGfAb4B3QH+Ah8CQQJkAogCrALRAvYD
+HANDA2oDkgO6A+MEDAQ2BGEEjAS4BOUFEgVABW4FoQXUBgkGPgZ1Bq4G5wcjB2AH
+nwffCCMIaAiwCPoJRwmWCegKPQqTCuwLRwurDA8MdgzeDUcNsw4gDo8O/w9yD+YQ
+WxDTEUwRxxJEEsITRhPMFFQU3xVrFfkWiRccF7EYSBjhGXwaGhq5G1ob/RymHVQe
+BB63H2wgJCDeIZsiWyMeI+MkqiV0JkEnDyfnKMQppSqJK3IsXi1PLkUvPzA9MT8y
+RDNMNFo1bDZ+N5E4oTmuOrc7uzy5PbM+qD+aQIpBd0JoQ11EVUVORkhHREhBST5K
+PEs6TDhNNk40TzNQMVEvUjlTSFRYVWpWfFePWKNZtlrJW9xc7l4AXxJgI2E1YkZj
+WWRuZYRmnme5aNdp9msYbDttYG6Gb6xw03H6cyJ0SnV0dqN31XkKekN7gXzFfhF/
+ZIDBgiaDlIULhomIDomzi3KNNI76kMOSkpRlljyYGJn3m9mdv5+6obujv6XIp9Wp
+56v9rhiwNrJZtH62pLjMuvW9Ib9RwYPDusX0yDTKd8zDzybRi9Pz1lrYwdsl3Yjf
+6eJK5KrnCukv6y7tFu7n8KryZ/Qr9gT4BPpD/OP//wAAABIANQBbAIMArADVAP4B
+KQFVAYMBqwHRAfgCIQJKAnUCoALNAvoDKQNYA4gDuQPqBB0EUASEBLkE7wUmBV4F
+mgXYBhgGWgadBuIHKgd0B8EIEAhjCLkJEwlxCdIKNwqfCwoLewvzDG4M6w1qDe0O
+cQ75D4MQEBCgETIRxxJeEvgTlBQyFNIVdRYaFsIXbRgbGMwZfxo2Gu8bqhxpHS8d
++B7DH5IgZCE5IhIi7iPNJK8llSZ9J2koXClSKkwrSSxLLVAuWi9nMHgxjTKlM8A0
+5TYNNzk4aTmdOtY8FD1YPqA/7UE+QptEBEVxRuZIY0nrS4BNIU7RUIxSF1NkVLJW
+AldUWKhZ/1tbXLleHV+FYPFiYmO6ZRBmaGfBaRxqe2vdbURur3AgcZdzE3SUdfp3
+VniyehB7b3zQfjV/nYEKgnyD9IVyhvWIfonTix2MaI2zjv+QSZGTktyUI5VplqyX
+75kvmm+brpzsni6fgqDbojqjoaUQpoioC6mZqzGs1K6AsDKx6rOmtWi3Lrj3usC8
+i75VwB/B6MOvxXTHN8j5yrrMec4uz+TRm9NU1Q3WyNiD2j7b+d20327hKeLj5J7m
+Ked+6M7qF+tZ7JHtuu7V7+fw4/Hb8r/zoPRw9UH1//a993P4I/jU+Xj6HfrA+1z7
++PyS/Sf9vP5Q/uD/b///AABzZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7
+ov///aMAAAPcAADAbG1tb2QAAAAAAAAGEAAAnKUAAAAAw7GoAAAAAAAAAAAAAAAA
+AAAAAAD/4QCARXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAA
+SgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAA
+AQAAAEgAAAABAAKgAgAEAAAAAQAAADugAwAEAAAAAQAAAFMAAAAA/9sAQwACAQEC
+AQECAgECAgICAgMFAwMDAwMGBAQDBQcGBwcHBgYGBwgLCQcICggGBgkNCQoLCwwM
+DAcJDQ4NDA4LDAwL/9sAQwECAgIDAgMFAwMFCwgGCAsLCwsLCwsLCwsLCwsLCwsL
+CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsL/8AAEQgAUwA7AwEiAAIR
+AQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMC
+BAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJ
+ChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3
+eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS
+09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAA
+AAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEH
+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
+DyXQOcA=
+=x0WA
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub   rsa4096 2015-11-15 [SC]
+      FFA9129A180D765B7A5BEA1C9B432B27D1BA20D7
+uid           [desconocida] Fredrik Roubert <fredrik@roubert.name>
+sig          C191C1EE0DED33EA 2015-11-23  [ID de usuario no encontrado]
+sig          216D7E92EB61819E 2015-11-25  [ID de usuario no encontrado]
+sig          1C2C9D2A7564DC9F 2015-12-02  [ID de usuario no encontrado]
+sig          A42898C74BF155DB 2015-12-03  [ID de usuario no encontrado]
+sig 3        C44AB8B850327DF9 2015-11-15  [ID de usuario no encontrado]
+sig          4719E4FC1E16C930 2015-12-02  [ID de usuario no encontrado]
+sig          4484F5552D1E8BB4 2015-12-02  [ID de usuario no encontrado]
+sig          6C6580E77BD756C4 2015-12-02  [ID de usuario no encontrado]
+sig          7F61756177978F76 2015-12-08  [ID de usuario no encontrado]
+sig          47712171F2ED62FB 2016-04-06  [ID de usuario no encontrado]
+sig 2        80D88B22D4330331 2015-11-21  [ID de usuario no encontrado]
+sig 3        9C187BA29B2157F8 2015-12-01  [ID de usuario no encontrado]
+sig 3        6DFD2ACE211BAAD0 2015-11-23  [ID de usuario no encontrado]
+sig 3        4445C665FFAD9AE0 2015-11-23  [ID de usuario no encontrado]
+sig 3        2DFF526BB17F76C6 2016-06-11  [ID de usuario no encontrado]
+sig 3        9B432B27D1BA20D7 2015-11-15  Fredrik Roubert <fredrik@roubert.name>
+uid           [desconocida] Fredrik Roubert <roubert@google.com>
+sig          C191C1EE0DED33EA 2015-11-23  [ID de usuario no encontrado]
+sig          216D7E92EB61819E 2015-11-25  [ID de usuario no encontrado]
+sig          1C2C9D2A7564DC9F 2015-12-02  [ID de usuario no encontrado]
+sig          A42898C74BF155DB 2015-12-03  [ID de usuario no encontrado]
+sig 3        C44AB8B850327DF9 2015-11-15  [ID de usuario no encontrado]
+sig          4719E4FC1E16C930 2015-12-02  [ID de usuario no encontrado]
+sig          4484F5552D1E8BB4 2015-12-02  [ID de usuario no encontrado]
+sig          6C6580E77BD756C4 2015-12-02  [ID de usuario no encontrado]
+sig          7F61756177978F76 2015-12-08  [ID de usuario no encontrado]
+sig          47712171F2ED62FB 2016-04-06  [ID de usuario no encontrado]
+sig 2        80D88B22D4330331 2015-11-21  [ID de usuario no encontrado]
+sig 3        9C187BA29B2157F8 2015-12-01  [ID de usuario no encontrado]
+sig 3        6DFD2ACE211BAAD0 2015-11-23  [ID de usuario no encontrado]
+sig 3        4445C665FFAD9AE0 2015-11-23  [ID de usuario no encontrado]
+sig 3        2DFF526BB17F76C6 2016-06-11  [ID de usuario no encontrado]
+sig 3        9B432B27D1BA20D7 2015-11-15  Fredrik Roubert <fredrik@roubert.name>
+sub   rsa4096 2015-11-15 [E]
+sig          9B432B27D1BA20D7 2015-11-15  Fredrik Roubert <fredrik@roubert.name>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=vIM2
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub   rsa4096 2018-06-28 [SC]
+      827320CB5E847C916CF49D06147473802F35F6CB
+uid           [ultimate] Jeff Genovy <jefgen@microsoft.com>
+sig 3        147473802F35F6CB 2019-12-04  Jeff Genovy <jefgen@microsoft.com>
+uid           [ultimate] Jeff Genovy <Jeff.Genovy@microsoft.com>
+sig 3        147473802F35F6CB 2019-12-04  Jeff Genovy <jefgen@microsoft.com>
+sub   rsa4096 2018-06-28 [E]
+sig          147473802F35F6CB 2018-06-28  Jeff Genovy <jefgen@microsoft.com>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFs1QYIBEACyx/qJBfSY1EbCQ4aJTY4QE2R/u2cqCa/mpPMDje+GDZ6SyBwj
+PrXx7W7kQcwTTGrylJd1A6Wnx4PwAS3cCl7vSExYOsEbxKUcZiHVweMQBDNHFfL6
+bmdsXrHD0ypWqyCmbWdSGdwXfYhlX3UlntoETgHBrwZ+qf6Uu70cDm7cKPEoPlWz
+2eg6evT0vgtD1Y/47x5zAyCVqgC+rsEJKVdK3X3QSoUerFiYRUEZDXBc9KfHrn2I
++St9fflVz6cNFExuc2x4H3b2vOwjZJqFO/cq47ppYXmOwbPQtH2r3hFpNxOIlQih
+h9MfWNiVKRICJZLZFicnFyANJVxK3ApK2Xhw4gJUjkhyXMZcpW891ETyOyuNjuDP
+cL0U6SqggfH0aubIfqBhgZqwTCp64Ckq28tjFqR3r7YqEFpiRu5mtO0gvk3sWl69
+bxXm0OxKLhhiVu0is3tokQU4M7zl7J8MHygBCkowoun/aw9Vis6K8ibItHb4CjTi
+SGGjNRbJxcPFq2YrU/c26T4IwtL+Mv59toXO0rJuwcaommkQ+G5zlBNViciyrOC4
+OzMiOkOrtYa6qaChAPfGrWL9ZETOBtVzZGpqLhYvTwP6Q7bDFoogtCq6iCU09FRU
+Q0fe3eJCeMFmVh84SWsdIe/GasXtWhvjlcmqnpz59Tzym8ZCDxhFaQt6CwARAQAB
+tCdKZWZmIEdlbm92eSA8SmVmZi5HZW5vdnlAbWljcm9zb2Z0LmNvbT6JAk4EEwEI
+ADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQSCcyDLXoR8kWz0nQYUdHOA
+LzX2ywUCXegVDAAKCRAUdHOALzX2y8NKD/9Ac7MhdVXmaoIjTNBQA/ZbZTipzLkC
+RxCiUai2ThMHIZKSyWFszVySHSvw0Cj8ZFUuDW61HliT6uYS/t3M93Wh1fTC4+qd
+Y0u0RVffhWIYxoW5pzo5p00L6Lb3oMfY6QuvLgvQd6iP0gXMQyUr/hC1kVOFJ9TX
+16ylf4GwSpJhKPXF+Heu5jVgDw2Qx/22/xl6xSsPRqTU4rc5HOQmHr5EfU3LjmXX
+PtSBXcknV1TSA/0Nbdxm5vpYQ2tdDnq/c0RU0B7L/mxOy8gH6wWR8qM3x0vpCnV1
+hu9U7Rh6ldOpd5FEVBeDluNQZMIEQHBAZ174UCkvcS/x0RgBa3ZwjgBGYpanonJ1
+qPcEqN4qWt3uXWuVxtNyM0rFgtpJ6fhF6rGyHo7nasI68a9XEbUh5IsKcDttTZgz
+blLgHHs0IyXyHG2DYG8wr18viiLo8Vt5QpLPIQT9tAgnRoiD83kO1IUTktksz/jE
+sGzf2gbgGTYWomM11W8iMXL6flBdhY5oasiP6jwPTtpLjmqCLZkz9hEJ7NBgOi3+
+Aqeu0PMwets0WQW6S2OzlHDGqprWQvVqOSa0XRXSJT7ZSlGImMMZMiUMpVukJjCT
+N2z8lOxpw2s9AL9jfvCD7TodpfmGd1SHNTNRv/Ivt2eHrMhfJ29zabIfPb1nPChK
+b1EpNlfgeNl64bQiSmVmZiBHZW5vdnkgPGplZmZnZW5vdnlAZ21haWwuY29tPokC
+TgQTAQgAOAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBIJzIMtehHyRbPSd
+BhR0c4AvNfbLBQJd6BUQAAoJEBR0c4AvNfbL1YYQAJ6MocZlLZ2107lYKOCPcCRy
+dnR4xi0t1jPOoSV6KNyC/frRppVzBodPGjAY6RfRM5jq6IVhqD6Nf9HEYydbn1oe
+FdD/mCXLiqtI2AOvVCzMJctoKo2NlxcnHQGJCvIEjMts6lWi4wDqAgTxOL6hov6Y
+HzsFjcDTZ3cVU51nFHM1tHLjYFYMALDy7CJ87k1GB3mTSAX0SIC7FVJmDWO3ooVP
+rqMofUvnlzBfHfJUfDsrOFeZZWHy4DXqHpMMebY9WLJv9W0LwgcLKugS+uxy98Zr
+QcQgHLh7Nl3yuYtftWL1bqAmBx4kTjQ3DAXDa3WYZQhV0DEZzRQP5pvlqkQoKp+x
+y//SzoFni55bJpH36F3Arp3flgFBpqy68ll3Y0/aOJ+jLD0O6/xQYPfG4Pu/Fly4
+28GQegfq6I/o+bc1k55ncT4+jpNb2a8n9TaFIs/uM2guowUisqt6WkB9jXrC7a0Z
+Cybt5iNBOuQVIZyz+BQvRMxkt7uESDPgo8cVAzr6DfX+GdBVAcZjm3piXWkaDxlE
+mOOW5HMW/3uOD2SAVH3+mPdvC37yFkPuTEoDbsgKRMIGolb3NVJVUu8+Hxyg0818
+h0G/zpE8XGNzAL52NrEsGyu8jN3L1BRFeClrP+xDas1I7lcohUXUHSnxJnA1GbKZ
+P2jq1DDDE3o06Ld3BFGntCJKZWZmIEdlbm92eSA8amVmZ2VuQG1pY3Jvc29mdC5j
+b20+iQJOBBMBCAA4AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEgnMgy16E
+fJFs9J0GFHRzgC819ssFAl3oFREACgkQFHRzgC819suQhQ//eepmASOFTA5CRegl
+Y9hzF0RP6+9kq+KTSbstbbQQuR4Vd2m0QeF4gT8vcIHEIfxVn6sfJFf2k4v/TKGE
+OFHXw8Wl4/XvquVpfp8x8pZ/XVd+/K9F1o6WZ/o2UUleEecIJENeSzJ69/WbGozE
+8HkSTaA4BR/G5bAzX79Rm0JfiS9l8ZyapkcPfSGO/Jcz1pkBfacAPyyDMxYFos6O
+y038D/2qSCLI3TxS/kS2FANpCpXwNUjvR04WfbMWnaVnOih/gqau7ZVQ20lpKZOY
+E4GcQtXVbaTR9vJ1tayA8FVpSO/4nqjD3CdI9JLkq7MGLnkHOdL/YtD0k+HtW8dr
+5p8m+tgjTmt7dAiCIXI+a8M4jjoIx/qAdHOOH/4T92s+zNYXd7CBkRp/6ipalfn+
+QnyFgL0r0z1P7hSwFckWKsbvT2CIFRgJOwoTAMJ26HsIqt9ZkMMwPwth+nYKRlw4
+WgmbZeoHZp0tpyqa7LTqNxVVxdx4rcgTL+jOOJMw+cQv4opv/pN7rWyFP6jCy5Wg
+DzmyrPZR/zEhH0h0cRLblq7Fuvl3t/pXxgWSAVYmAvTQyIwRWC0Nvec/AVRGE5uF
+koXM6nl27ZtGc7PwmqJZePi54RDIy7LCI09zdmu50JALfxkQ0Yg4EVFy+gf979jy
+ey7Fz42xM7+BTjQ6lXdmuSnIbFe5Ag0EWzVBggEQAL8RWXQwK1jupZkKCoGSSmuc
+FO9MdCS/744340u9TU0oFY8mmqOppoOiVi9EKIOWVHJ5a5DixsIdNkTAtmXM4a6u
+sr5wB555+KTkmofJ8nzHQM7gEaaHt9JErNo0f7Fzi9VEJ+G1XHFjW80HvQ9krpSj
+Lz3x0CbD4KjRRJWoUrKiBvNJjk2Xox28pA9F7lHWLgGTgZFrtCWMaViOcZqBZfAl
+pXYFR4hacddsDrRw4r4cl3NlfQ+SS4PL2kCcH1gx5AlhRkygtiJfYrHDvHpBk6rz
+r/IMojXOUAYV8TFQRyhsz/Cpx6rAun+aOXQlL4eDuNtWnxEeoHoNRAnAtUobP8iv
+cNqY1F3ZWaaY/MmNtw/FiDmYePzLz9p8FhBHKvE20Yt6UrUX+E9fPPSQDZxdtTzy
+LOWRUtOhMJIPigQRipFWng9d79Rf/goX5fcSPja/eqZaKkosYVlJW09+MxLkNO2W
+/UDmoVsvhnUK77I8BxqgrZUI8uj+d2cO+WQfL/RlGJ7a+icspycT8nTeEfCqjarQ
+wzNY5PLo6FN+N8dLVRyrQsPwwfWstA/6DJaRHgwhz6UdV7wYOBtI35xIZ8Cy71tT
+PycgOiUmatM8M5/INvqqPmQwl3VQdvrsD8MV3dP/U3edCSeVDKhqFXps47zdh/Ji
+gTssKOz6Lafg8Uo3314zABEBAAGJAjYEGAEIACAWIQSCcyDLXoR8kWz0nQYUdHOA
+LzX2ywUCWzVBggIbDAAKCRAUdHOALzX2yx0qD/9Wr1rnH2GZMwOCpwAplRegw/I5
+PNS36fOYs2YEv6/g3OdgSrGu2ZL+VqhCRTaqE7UrJDIsV9JORRptgg48nw5IGQlq
+NyyxMEJxu7KlpgRcKC6o1hZ+zqkLyQGdcd29i8AWBKU++MUunVMUplVuQa2mDRon
+KpN2lg4y2djfXvLOiKo7kLXnM8S+42gB34+X8HqFhfTXwz0Q/oroHayrU4ncTEob
+D81bOSQ2agn0Yi5GNCS6FR1Vmbto3j5HgvLbn9WkT8cM+nBr7F2zsZtG1Op+SKZK
+KJ9/eHkMJ/9XgZMcaEPJzD938+AscFUZeAL0QUS8MRlyYLFQKvQHiZDGgwfDcFGs
+7X9kZbMdx8nKRej8wqMOcro/TfogKSJj04L3qtsa5Cs71oVeUBalIlEcVkZIWUNS
+HzwDFcJtfh1lbjRm9ALLTEHwhoZ6/OxRRbixEUlGZGCn754Jt2JrcQGm+wqL/w2P
+ryG1zQFz5bcfxofFF/YxpHOsrMXb2GkAC1Wg9ypGfQ1RStGCe2q+6Qwo+csO7lyQ
+mGdooN2u+X2SXbBq+F2JxQe2X65SAWrFsmflN1vsY22IWExQE9kA63twjQu3iAF/
+mrLU2gvbaFZtV1HwYC3bCNqlx68rchjSQwOI5sdocwWsWbvJ28yi5I0PcBmyBa0Y
+TMuS5W4GIP4f7uR1uQ==
+=Veoq
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/icu4c/source/common/uloc_tag.cpp b/icu4c/source/common/uloc_tag.cpp
index 1c10c48..2b76a92 100644
--- a/icu4c/source/common/uloc_tag.cpp
+++ b/icu4c/source/common/uloc_tag.cpp
@@ -1110,6 +1110,19 @@
     }
 }
 
+static void _sortVariants(VariantListEntry* first) {
+    for (VariantListEntry* var1 = first; var1 != NULL; var1 = var1->next) {
+        for (VariantListEntry* var2 = var1->next; var2 != NULL; var2 = var2->next) {
+            // Swap var1->variant and var2->variant.
+            if (uprv_compareInvCharsAsAscii(var1->variant, var2->variant) > 0) {
+                const char* temp = var1->variant;
+                var1->variant = var2->variant;
+                var2->variant = temp;
+            }
+        }
+    }
+}
+
 static void
 _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool *hadPosix, UErrorCode* status) {
     char buf[ULOC_FULLNAME_CAPACITY];
@@ -1199,6 +1212,9 @@
             if (varFirst != NULL) {
                 int32_t varLen;
 
+                /* per UTS35, we should sort the variants */
+                _sortVariants(varFirst);
+
                 /* write out validated/normalized variants to the target */
                 var = varFirst;
                 while (var != NULL) {
@@ -2822,6 +2838,7 @@
     }
 
     /* variants */
+    _sortVariants(lt.getAlias()->variants);
     n = ultag_getVariantsSize(lt.getAlias());
     if (n > 0) {
         if (noRegion) {
diff --git a/icu4c/source/i18n/decimfmt.cpp b/icu4c/source/i18n/decimfmt.cpp
index d19f651..4015250 100644
--- a/icu4c/source/i18n/decimfmt.cpp
+++ b/icu4c/source/i18n/decimfmt.cpp
@@ -1834,7 +1834,8 @@
     char16_t localBuffer[localCapacity];
     char16_t* ptr = localBuffer + localCapacity;
     int8_t group = 0;
-    for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < fields->fastData.minInt); i++) {
+    int8_t minInt = (fields->fastData.minInt < 1)? 1: fields->fastData.minInt;
+    for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < minInt); i++) {
         if (group++ == 3 && fields->fastData.cpGroupingSeparator != 0) {
             *(--ptr) = fields->fastData.cpGroupingSeparator;
             group = 1;
diff --git a/icu4c/source/i18n/dtptngen.cpp b/icu4c/source/i18n/dtptngen.cpp
index c5f8618..4948d2c 100644
--- a/icu4c/source/i18n/dtptngen.cpp
+++ b/icu4c/source/i18n/dtptngen.cpp
@@ -2162,6 +2162,25 @@
         }
         skeletonResult.type[field] = subField;
     }
+
+    // #20739, we have a skeleton with milliseconde, but no seconds
+    if (!skeletonResult.original.isFieldEmpty(UDATPG_FRACTIONAL_SECOND_FIELD)
+        && skeletonResult.original.isFieldEmpty(UDATPG_SECOND_FIELD)) {
+        // Force the use of seconds
+        for (i = 0; dtTypes[i].patternChar != 0; i++) {
+            if (dtTypes[i].field == UDATPG_SECOND_FIELD) {
+                // first entry for UDATPG_SECOND_FIELD
+                skeletonResult.original.populate(UDATPG_SECOND_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen);
+                skeletonResult.baseOriginal.populate(UDATPG_SECOND_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen);
+                // We add value.length, same as above, when type is first initialized.
+                // The value we want to "fake" here is "s", and 1 means "s".length()
+                int16_t subField = dtTypes[i].type;
+                skeletonResult.type[UDATPG_SECOND_FIELD] = (subField > 0) ? subField + 1 : subField;
+                break;
+            }
+        }
+    }
+
     // #13183, handle special behavior for day period characters (a, b, B)
     if (!skeletonResult.original.isFieldEmpty(UDATPG_HOUR_FIELD)) {
         if (skeletonResult.original.getFieldChar(UDATPG_HOUR_FIELD)==LOW_H || skeletonResult.original.getFieldChar(UDATPG_HOUR_FIELD)==CAP_K) {
diff --git a/icu4c/source/i18n/number_compact.cpp b/icu4c/source/i18n/number_compact.cpp
index 3d25999..e3c6bbc 100644
--- a/icu4c/source/i18n/number_compact.cpp
+++ b/icu4c/source/i18n/number_compact.cpp
@@ -215,19 +215,25 @@
 /// END OF CompactData.java; BEGIN CompactNotation.java ///
 ///////////////////////////////////////////////////////////
 
-CompactHandler::CompactHandler(CompactStyle compactStyle, const Locale &locale, const char *nsName,
-                               CompactType compactType, const PluralRules *rules,
-                               MutablePatternModifier *buildReference, const MicroPropsGenerator *parent,
-                               UErrorCode &status)
-        : rules(rules), parent(parent) {
+CompactHandler::CompactHandler(
+        CompactStyle compactStyle,
+        const Locale &locale,
+        const char *nsName,
+        CompactType compactType,
+        const PluralRules *rules,
+        MutablePatternModifier *buildReference,
+        bool safe,
+        const MicroPropsGenerator *parent,
+        UErrorCode &status)
+        : rules(rules), parent(parent), safe(safe) {
     data.populate(locale, nsName, compactStyle, compactType, status);
-    if (buildReference != nullptr) {
+    if (safe) {
         // Safe code path
         precomputeAllModifiers(*buildReference, status);
-        safe = TRUE;
     } else {
         // Unsafe code path
-        safe = FALSE;
+        // Store the MutablePatternModifier reference.
+        unsafePatternModifier = buildReference;
     }
 }
 
@@ -309,8 +315,9 @@
         // C++ Note: Use unsafePatternInfo for proper lifecycle.
         ParsedPatternInfo &patternInfo = const_cast<CompactHandler *>(this)->unsafePatternInfo;
         PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
-        static_cast<MutablePatternModifier*>(const_cast<Modifier*>(micros.modMiddle))
-            ->setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD);
+        unsafePatternModifier->setPatternInfo(&unsafePatternInfo, UNUM_COMPACT_FIELD);
+        unsafePatternModifier->setNumberProperties(quantity.signum(), StandardPlural::Form::COUNT);
+        micros.modMiddle = unsafePatternModifier;
     }
 
     // We already performed rounding. Do not perform it again.
diff --git a/icu4c/source/i18n/number_compact.h b/icu4c/source/i18n/number_compact.h
index dda5f9f..199d39f 100644
--- a/icu4c/source/i18n/number_compact.h
+++ b/icu4c/source/i18n/number_compact.h
@@ -56,10 +56,16 @@
 
 class CompactHandler : public MicroPropsGenerator, public UMemory {
   public:
-    CompactHandler(CompactStyle compactStyle, const Locale &locale, const char *nsName,
-                   CompactType compactType, const PluralRules *rules,
-                   MutablePatternModifier *buildReference, const MicroPropsGenerator *parent,
-                   UErrorCode &status);
+    CompactHandler(
+            CompactStyle compactStyle,
+            const Locale &locale,
+            const char *nsName,
+            CompactType compactType,
+            const PluralRules *rules,
+            MutablePatternModifier *buildReference,
+            bool safe,
+            const MicroPropsGenerator *parent,
+            UErrorCode &status);
 
     ~CompactHandler() U_OVERRIDE;
 
@@ -74,6 +80,7 @@
     int32_t precomputedModsLength = 0;
     CompactData data;
     ParsedPatternInfo unsafePatternInfo;
+    MutablePatternModifier* unsafePatternModifier;
     UBool safe;
 
     /** Used by the safe code path */
diff --git a/icu4c/source/i18n/number_decimalquantity.cpp b/icu4c/source/i18n/number_decimalquantity.cpp
index 2c4c2ce..abbc23d 100644
--- a/icu4c/source/i18n/number_decimalquantity.cpp
+++ b/icu4c/source/i18n/number_decimalquantity.cpp
@@ -319,10 +319,14 @@
 }
 
 Signum DecimalQuantity::signum() const {
-    if (isNegative()) {
+    bool isZero = (isZeroish() && !isInfinite());
+    bool isNeg = isNegative();
+    if (isZero && isNeg) {
+        return SIGNUM_NEG_ZERO;
+    } else if (isZero) {
+        return SIGNUM_POS_ZERO;
+    } else if (isNeg) {
         return SIGNUM_NEG;
-    } else if (isZeroish() && !isInfinite()) {
-        return SIGNUM_ZERO;
     } else {
         return SIGNUM_POS;
     }
diff --git a/icu4c/source/i18n/number_formatimpl.cpp b/icu4c/source/i18n/number_formatimpl.cpp
index 2e2c4a9..708aaa5 100644
--- a/icu4c/source/i18n/number_formatimpl.cpp
+++ b/icu4c/source/i18n/number_formatimpl.cpp
@@ -111,7 +111,6 @@
         return;
     }
     fMicroPropsGenerator->processQuantity(inValue, microsOut, status);
-    microsOut.rounder.apply(inValue, status);
     microsOut.integerWidth.apply(inValue, status);
 }
 
@@ -124,7 +123,6 @@
         return fMicros; // must always return a value
     }
     fMicroPropsGenerator->processQuantity(inValue, fMicros, status);
-    fMicros.rounder.apply(inValue, status);
     fMicros.integerWidth.apply(inValue, status);
     return fMicros;
 }
@@ -384,11 +382,7 @@
         patternModifier->setSymbols(fMicros.symbols, currencySymbols, unitWidth, nullptr);
     }
     if (safe) {
-        fImmutablePatternModifier.adoptInstead(patternModifier->createImmutableAndChain(chain, status));
-        chain = fImmutablePatternModifier.getAlias();
-    } else {
-        patternModifier->addToChain(chain);
-        chain = patternModifier;
+        fImmutablePatternModifier.adoptInstead(patternModifier->createImmutable(status));
     }
 
     // Outer modifier (CLDR units and currency long names)
@@ -418,8 +412,6 @@
     }
 
     // Compact notation
-    // NOTE: Compact notation can (but might not) override the middle modifier and rounding.
-    // It therefore needs to go at the end of the chain.
     if (macros.notation.fType == Notation::NTN_COMPACT) {
         CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME)
                                   ? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL;
@@ -429,7 +421,8 @@
             nsName,
             compactType,
             resolvePluralRules(macros.rules, macros.locale, status),
-            safe ? patternModifier : nullptr,
+            patternModifier,
+            safe,
             chain,
             status);
         if (newCompactHandler == nullptr) {
@@ -440,6 +433,15 @@
         chain = fCompactHandler.getAlias();
     }
 
+    // Always add the pattern modifier as the last element of the chain.
+    if (safe) {
+        fImmutablePatternModifier->addToChain(chain);
+        chain = fImmutablePatternModifier.getAlias();
+    } else {
+        patternModifier->addToChain(chain);
+        chain = patternModifier;
+    }
+
     return chain;
 }
 
@@ -507,6 +509,12 @@
 
         // Add the fraction digits
         length += writeFractionDigits(micros, quantity, string, length + index, status);
+
+        if (length == 0) {
+            // Force output of the digit for value 0
+            length += utils::insertDigitFromSymbols(
+                    string, index, 0, *micros.symbols, UNUM_INTEGER_FIELD, status);
+        }
     }
 
     return length;
diff --git a/icu4c/source/i18n/number_formatimpl.h b/icu4c/source/i18n/number_formatimpl.h
index 206c5f5..084bc4a 100644
--- a/icu4c/source/i18n/number_formatimpl.h
+++ b/icu4c/source/i18n/number_formatimpl.h
@@ -95,7 +95,7 @@
     LocalPointer<const ParsedPatternInfo> fPatternInfo;
     LocalPointer<const ScientificHandler> fScientificHandler;
     LocalPointer<MutablePatternModifier> fPatternModifier;
-    LocalPointer<const ImmutablePatternModifier> fImmutablePatternModifier;
+    LocalPointer<ImmutablePatternModifier> fImmutablePatternModifier;
     LocalPointer<const LongNameHandler> fLongNameHandler;
     LocalPointer<const CompactHandler> fCompactHandler;
 
diff --git a/icu4c/source/i18n/number_longnames.cpp b/icu4c/source/i18n/number_longnames.cpp
index 817aa0e..5519398 100644
--- a/icu4c/source/i18n/number_longnames.cpp
+++ b/icu4c/source/i18n/number_longnames.cpp
@@ -308,7 +308,7 @@
         if (U_FAILURE(status)) { return; }
         SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
         if (U_FAILURE(status)) { return; }
-        fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_ZERO, plural});
+        fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_POS_ZERO, plural});
     }
 }
 
@@ -325,7 +325,7 @@
         if (U_FAILURE(status)) { return; }
         SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
         if (U_FAILURE(status)) { return; }
-        fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_ZERO, plural});
+        fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_POS_ZERO, plural});
     }
 }
 
diff --git a/icu4c/source/i18n/number_mapper.cpp b/icu4c/source/i18n/number_mapper.cpp
index 40fd528..f0d313f 100644
--- a/icu4c/source/i18n/number_mapper.cpp
+++ b/icu4c/source/i18n/number_mapper.cpp
@@ -125,10 +125,8 @@
     }
     // Validate min/max int/frac.
     // For backwards compatibility, minimum overrides maximum if the two conflict.
-    // The following logic ensures that there is always a minimum of at least one digit.
     if (minInt == 0 && maxFrac != 0) {
-        // Force a digit after the decimal point.
-        minFrac = minFrac <= 0 ? 1 : minFrac;
+        minFrac = (minFrac < 0 || (minFrac == 0 && maxInt == 0)) ? 1 : minFrac;
         maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac;
         minInt = 0;
         maxInt = maxInt < 0 ? -1 : maxInt > kMaxIntFracSig ? -1 : maxInt;
diff --git a/icu4c/source/i18n/number_microprops.h b/icu4c/source/i18n/number_microprops.h
index d2393ae..56512f5 100644
--- a/icu4c/source/i18n/number_microprops.h
+++ b/icu4c/source/i18n/number_microprops.h
@@ -37,7 +37,7 @@
     // Note: This struct has no direct ownership of the following pointers.
     const DecimalFormatSymbols* symbols;
     const Modifier* modOuter;
-    const Modifier* modMiddle;
+    const Modifier* modMiddle = nullptr;
     const Modifier* modInner;
 
     // The following "helper" fields may optionally be used during the MicroPropsGenerator.
diff --git a/icu4c/source/i18n/number_modifiers.h b/icu4c/source/i18n/number_modifiers.h
index c84c6aa..e3820b6 100644
--- a/icu4c/source/i18n/number_modifiers.h
+++ b/icu4c/source/i18n/number_modifiers.h
@@ -319,12 +319,12 @@
 
   private:
     // NOTE: mods is zero-initialized (to nullptr)
-    const Modifier *mods[3 * StandardPlural::COUNT] = {};
+    const Modifier *mods[4 * StandardPlural::COUNT] = {};
 
     inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) {
-        U_ASSERT(signum >= -1 && signum <= 1);
+        U_ASSERT(signum >= 0 && signum < SIGNUM_COUNT);
         U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT);
-        return static_cast<int32_t>(plural) * 3 + (signum + 1);
+        return static_cast<int32_t>(plural) * SIGNUM_COUNT + signum;
     }
 };
 
diff --git a/icu4c/source/i18n/number_patternmodifier.cpp b/icu4c/source/i18n/number_patternmodifier.cpp
index 724f5b9..892ac37 100644
--- a/icu4c/source/i18n/number_patternmodifier.cpp
+++ b/icu4c/source/i18n/number_patternmodifier.cpp
@@ -55,12 +55,6 @@
 }
 
 ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& status) {
-    return createImmutableAndChain(nullptr, status);
-}
-
-ImmutablePatternModifier*
-MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* parent, UErrorCode& status) {
-
     // TODO: Move StandardPlural VALUES to standardplural.h
     static const StandardPlural::Form STANDARD_PLURAL_VALUES[] = {
             StandardPlural::Form::ZERO,
@@ -81,8 +75,10 @@
         for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) {
             setNumberProperties(SIGNUM_POS, plural);
             pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status));
-            setNumberProperties(SIGNUM_ZERO, plural);
-            pm->adoptModifier(SIGNUM_ZERO, plural, createConstantModifier(status));
+            setNumberProperties(SIGNUM_NEG_ZERO, plural);
+            pm->adoptModifier(SIGNUM_NEG_ZERO, plural, createConstantModifier(status));
+            setNumberProperties(SIGNUM_POS_ZERO, plural);
+            pm->adoptModifier(SIGNUM_POS_ZERO, plural, createConstantModifier(status));
             setNumberProperties(SIGNUM_NEG, plural);
             pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status));
         }
@@ -90,20 +86,22 @@
             delete pm;
             return nullptr;
         }
-        return new ImmutablePatternModifier(pm, fRules, parent);  // adopts pm
+        return new ImmutablePatternModifier(pm, fRules);  // adopts pm
     } else {
         // Faster path when plural keyword is not needed.
         setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
         pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status));
-        setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
-        pm->adoptModifierWithoutPlural(SIGNUM_ZERO, createConstantModifier(status));
+        setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
+        pm->adoptModifierWithoutPlural(SIGNUM_NEG_ZERO, createConstantModifier(status));
+        setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
+        pm->adoptModifierWithoutPlural(SIGNUM_POS_ZERO, createConstantModifier(status));
         setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
         pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status));
         if (U_FAILURE(status)) {
             delete pm;
             return nullptr;
         }
-        return new ImmutablePatternModifier(pm, nullptr, parent);  // adopts pm
+        return new ImmutablePatternModifier(pm, nullptr);  // adopts pm
     }
 }
 
@@ -120,13 +118,16 @@
     }
 }
 
-ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules,
-                                                   const MicroPropsGenerator* parent)
-        : pm(pm), rules(rules), parent(parent) {}
+ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules)
+        : pm(pm), rules(rules), parent(nullptr) {}
 
 void ImmutablePatternModifier::processQuantity(DecimalQuantity& quantity, MicroProps& micros,
                                                UErrorCode& status) const {
     parent->processQuantity(quantity, micros, status);
+    micros.rounder.apply(quantity, status);
+    if (micros.modMiddle != nullptr) {
+        return;
+    }
     applyToMicros(micros, quantity, status);
 }
 
@@ -148,6 +149,10 @@
     }
 }
 
+void ImmutablePatternModifier::addToChain(const MicroPropsGenerator* parent) {
+    this->parent = parent;
+}
+
 
 /** Used by the unsafe code path. */
 MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerator* parent) {
@@ -158,6 +163,10 @@
 void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& micros,
                                              UErrorCode& status) const {
     fParent->processQuantity(fq, micros, status);
+    micros.rounder.apply(fq, status);
+    if (micros.modMiddle != nullptr) {
+        return;
+    }
     // The unsafe code path performs self-mutation, so we need a const_cast.
     // This method needs to be const because it overrides a const method in the parent class.
     auto nonConstThis = const_cast<MutablePatternModifier*>(this);
@@ -263,7 +272,12 @@
 /** This method contains the heart of the logic for rendering LDML affix strings. */
 void MutablePatternModifier::prepareAffix(bool isPrefix) {
     PatternStringUtils::patternInfoToStringBuilder(
-            *fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, fPerMilleReplacesPercent, currentAffix);
+            *fPatternInfo,
+            isPrefix,
+            PatternStringUtils::resolveSignDisplay(fSignDisplay, fSignum),
+            fPlural,
+            fPerMilleReplacesPercent,
+            currentAffix);
 }
 
 UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const {
diff --git a/icu4c/source/i18n/number_patternmodifier.h b/icu4c/source/i18n/number_patternmodifier.h
index b2c90e0..4034c9a 100644
--- a/icu4c/source/i18n/number_patternmodifier.h
+++ b/icu4c/source/i18n/number_patternmodifier.h
@@ -50,9 +50,11 @@
 
     const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const;
 
+    // Non-const method:
+    void addToChain(const MicroPropsGenerator* parent);
+
   private:
-    ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules,
-                             const MicroPropsGenerator* parent);
+    ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules);
 
     const LocalPointer<AdoptingModifierStore> pm;
     const PluralRules* rules;
@@ -165,21 +167,6 @@
      */
     ImmutablePatternModifier *createImmutable(UErrorCode &status);
 
-    /**
-     * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable
-     * and can be saved for future use. The number properties in the current instance are mutated; all other properties
-     * are left untouched.
-     *
-     * <p>
-     * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
-     *
-     * @param parent
-     *            The QuantityChain to which to chain this immutable.
-     * @return An immutable that supports both positive and negative numbers.
-     */
-    ImmutablePatternModifier *
-    createImmutableAndChain(const MicroPropsGenerator *parent, UErrorCode &status);
-
     MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent);
 
     void processQuantity(DecimalQuantity &, MicroProps &micros, UErrorCode &status) const U_OVERRIDE;
diff --git a/icu4c/source/i18n/number_patternstring.cpp b/icu4c/source/i18n/number_patternstring.cpp
index c7212c1..55b83f1 100644
--- a/icu4c/source/i18n/number_patternstring.cpp
+++ b/icu4c/source/i18n/number_patternstring.cpp
@@ -1000,23 +1000,19 @@
 }
 
 void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
-                                                    Signum signum, UNumberSignDisplay signDisplay,
+                                                    PatternSignType patternSignType,
                                                     StandardPlural::Form plural,
                                                     bool perMilleReplacesPercent, UnicodeString& output) {
 
     // Should the output render '+' where '-' would normally appear in the pattern?
-    bool plusReplacesMinusSign = signum != -1 && (
-            signDisplay == UNUM_SIGN_ALWAYS || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS || (
-                    signum == 1 && (
-                            signDisplay == UNUM_SIGN_EXCEPT_ZERO ||
-                            signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO))) &&
-                                 patternInfo.positiveHasPlusSign() == false;
+    bool plusReplacesMinusSign = (patternSignType == PATTERN_SIGN_TYPE_POS_SIGN)
+        && !patternInfo.positiveHasPlusSign();
 
-    // Should we use the affix from the negative subpattern? (If not, we will use the positive
-    // subpattern.)
-    // TODO: Deal with signum
-    bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && (
-            signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
+    // Should we use the affix from the negative subpattern?
+    // (If not, we will use the positive subpattern.)
+    bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern()
+        && (patternSignType == PATTERN_SIGN_TYPE_NEG
+            || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
 
     // Resolve the flags for the affix pattern.
     int flags = 0;
@@ -1035,8 +1031,8 @@
     bool prependSign;
     if (!isPrefix || useNegativeAffixPattern) {
         prependSign = false;
-    } else if (signum == -1) {
-        prependSign = signDisplay != UNUM_SIGN_NEVER;
+    } else if (patternSignType == PATTERN_SIGN_TYPE_NEG) {
+        prependSign = true;
     } else {
         prependSign = plusReplacesMinusSign;
     }
@@ -1065,4 +1061,60 @@
     }
 }
 
+PatternSignType PatternStringUtils::resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum) {
+    switch (signDisplay) {
+        case UNUM_SIGN_AUTO:
+        case UNUM_SIGN_ACCOUNTING:
+            switch (signum) {
+                case SIGNUM_NEG:
+                case SIGNUM_NEG_ZERO:
+                    return PATTERN_SIGN_TYPE_NEG;
+                case SIGNUM_POS_ZERO:
+                case SIGNUM_POS:
+                    return PATTERN_SIGN_TYPE_POS;
+                default:
+                    break;
+            }
+            break;
+
+        case UNUM_SIGN_ALWAYS:
+        case UNUM_SIGN_ACCOUNTING_ALWAYS:
+            switch (signum) {
+                case SIGNUM_NEG:
+                case SIGNUM_NEG_ZERO:
+                    return PATTERN_SIGN_TYPE_NEG;
+                case SIGNUM_POS_ZERO:
+                case SIGNUM_POS:
+                    return PATTERN_SIGN_TYPE_POS_SIGN;
+                default:
+                    break;
+            }
+            break;
+
+        case UNUM_SIGN_EXCEPT_ZERO:
+        case UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO:
+            switch (signum) {
+                case SIGNUM_NEG:
+                    return PATTERN_SIGN_TYPE_NEG;
+                case SIGNUM_NEG_ZERO:
+                case SIGNUM_POS_ZERO:
+                    return PATTERN_SIGN_TYPE_POS;
+                case SIGNUM_POS:
+                    return PATTERN_SIGN_TYPE_POS_SIGN;
+                default:
+                    break;
+            }
+            break;
+
+        case UNUM_SIGN_NEVER:
+            return PATTERN_SIGN_TYPE_POS;
+
+        default:
+            break;
+    }
+
+    UPRV_UNREACHABLE;
+    return PATTERN_SIGN_TYPE_POS;
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/i18n/number_patternstring.h b/icu4c/source/i18n/number_patternstring.h
index 1191d29..54f37fd 100644
--- a/icu4c/source/i18n/number_patternstring.h
+++ b/icu4c/source/i18n/number_patternstring.h
@@ -22,6 +22,18 @@
 // Forward declaration
 class PatternParser;
 
+// Note: the order of fields in this enum matters for parsing.
+enum PatternSignType {
+    /** Render using normal positive subpattern rules */
+    PATTERN_SIGN_TYPE_POS,
+    /** Render using rules to force the display of a plus sign */
+    PATTERN_SIGN_TYPE_POS_SIGN,
+    /** Render using negative subpattern rules */
+    PATTERN_SIGN_TYPE_NEG,
+    /** Count for looping over the possibilities */
+    PATTERN_SIGN_TYPE_COUNT
+};
+
 // Exported as U_I18N_API because it is a public member field of exported ParsedSubpatternInfo
 struct U_I18N_API Endpoints {
     int32_t start = 0;
@@ -295,10 +307,12 @@
      * substitution, and plural forms for CurrencyPluralInfo.
      */
     static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
-                                           Signum signum, UNumberSignDisplay signDisplay,
+                                           PatternSignType patternSignType,
                                            StandardPlural::Form plural, bool perMilleReplacesPercent,
                                            UnicodeString& output);
 
+    static PatternSignType resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum);
+
   private:
     /** @return The number of chars inserted. */
     static int escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex,
diff --git a/icu4c/source/i18n/number_rounding.cpp b/icu4c/source/i18n/number_rounding.cpp
index 813d4b6..3ffce67 100644
--- a/icu4c/source/i18n/number_rounding.cpp
+++ b/icu4c/source/i18n/number_rounding.cpp
@@ -294,9 +294,7 @@
 }
 
 RoundingImpl RoundingImpl::passThrough() {
-    RoundingImpl retval;
-    retval.fPassThrough = true;
-    return retval;
+    return {};
 }
 
 bool RoundingImpl::isSignificantDigits() const {
diff --git a/icu4c/source/i18n/number_roundingutils.h b/icu4c/source/i18n/number_roundingutils.h
index 9c2c47b..3e37f31 100644
--- a/icu4c/source/i18n/number_roundingutils.h
+++ b/icu4c/source/i18n/number_roundingutils.h
@@ -150,7 +150,7 @@
  */
 class RoundingImpl {
   public:
-    RoundingImpl() = default;  // default constructor: leaves object in undefined state
+    RoundingImpl() = default;  // defaults to pass-through rounder
 
     RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode,
                  const CurrencyUnit& currency, UErrorCode& status);
@@ -186,7 +186,7 @@
   private:
     Precision fPrecision;
     UNumberFormatRoundingMode fRoundingMode;
-    bool fPassThrough;
+    bool fPassThrough = true;  // default value
 };
 
 
diff --git a/icu4c/source/i18n/number_types.h b/icu4c/source/i18n/number_types.h
index d62aa6a..641e082 100644
--- a/icu4c/source/i18n/number_types.h
+++ b/icu4c/source/i18n/number_types.h
@@ -92,9 +92,11 @@
 };
 
 enum Signum {
-    SIGNUM_NEG = -1,
-    SIGNUM_ZERO = 0,
-    SIGNUM_POS = 1
+    SIGNUM_NEG = 0,
+    SIGNUM_NEG_ZERO = 1,
+    SIGNUM_POS_ZERO = 2,
+    SIGNUM_POS = 3,
+    SIGNUM_COUNT = 4,
 };
 
 
diff --git a/icu4c/source/i18n/numparse_affixes.cpp b/icu4c/source/i18n/numparse_affixes.cpp
index cf8bab4..ca293e7 100644
--- a/icu4c/source/i18n/numparse_affixes.cpp
+++ b/icu4c/source/i18n/numparse_affixes.cpp
@@ -271,8 +271,6 @@
     // Use initial capacity of 6, the highest possible number of AffixMatchers.
     UnicodeString sb;
     bool includeUnpaired = 0 != (parseFlags & PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES);
-    UNumberSignDisplay signDisplay = (0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) ? UNUM_SIGN_ALWAYS
-                                                                                        : UNUM_SIGN_AUTO;
 
     int32_t numAffixMatchers = 0;
     int32_t numAffixPatternMatchers = 0;
@@ -281,13 +279,23 @@
     AffixPatternMatcher* posSuffix = nullptr;
 
     // Pre-process the affix strings to resolve LDML rules like sign display.
-    for (int8_t signumInt = 1; signumInt >= -1; signumInt--) {
-        auto signum = static_cast<Signum>(signumInt);
+    for (int8_t typeInt = 0; typeInt < PATTERN_SIGN_TYPE_COUNT; typeInt++) {
+        auto type = static_cast<PatternSignType>(typeInt);
+
+        // Skip affixes in some cases
+        if (type == PATTERN_SIGN_TYPE_POS
+                && 0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
+            continue;
+        }
+        if (type == PATTERN_SIGN_TYPE_POS_SIGN
+                && 0 == (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
+            continue;
+        }
 
         // Generate Prefix
         bool hasPrefix = false;
         PatternStringUtils::patternInfoToStringBuilder(
-                patternInfo, true, signum, signDisplay, StandardPlural::OTHER, false, sb);
+                patternInfo, true, type, StandardPlural::OTHER, false, sb);
         fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
                 sb, *fTokenWarehouse, parseFlags, &hasPrefix, status);
         AffixPatternMatcher* prefix = hasPrefix ? &fAffixPatternMatchers[numAffixPatternMatchers++]
@@ -296,13 +304,13 @@
         // Generate Suffix
         bool hasSuffix = false;
         PatternStringUtils::patternInfoToStringBuilder(
-                patternInfo, false, signum, signDisplay, StandardPlural::OTHER, false, sb);
+                patternInfo, false, type, StandardPlural::OTHER, false, sb);
         fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
                 sb, *fTokenWarehouse, parseFlags, &hasSuffix, status);
         AffixPatternMatcher* suffix = hasSuffix ? &fAffixPatternMatchers[numAffixPatternMatchers++]
                                                 : nullptr;
 
-        if (signum == 1) {
+        if (type == PATTERN_SIGN_TYPE_POS) {
             posPrefix = prefix;
             posSuffix = suffix;
         } else if (equals(prefix, posPrefix) && equals(suffix, posSuffix)) {
@@ -311,17 +319,17 @@
         }
 
         // Flags for setting in the ParsedNumber; the token matchers may add more.
-        int flags = (signum == -1) ? FLAG_NEGATIVE : 0;
+        int flags = (type == PATTERN_SIGN_TYPE_NEG) ? FLAG_NEGATIVE : 0;
 
         // Note: it is indeed possible for posPrefix and posSuffix to both be null.
         // We still need to add that matcher for strict mode to work.
         fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags};
         if (includeUnpaired && prefix != nullptr && suffix != nullptr) {
             // The following if statements are designed to prevent adding two identical matchers.
-            if (signum == 1 || !equals(prefix, posPrefix)) {
+            if (type == PATTERN_SIGN_TYPE_POS || !equals(prefix, posPrefix)) {
                 fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags};
             }
-            if (signum == 1 || !equals(suffix, posSuffix)) {
+            if (type == PATTERN_SIGN_TYPE_POS || !equals(suffix, posSuffix)) {
                 fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags};
             }
         }
diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp
index 5fcbb58..6246e8f 100644
--- a/icu4c/source/i18n/smpdtfmt.cpp
+++ b/icu4c/source/i18n/smpdtfmt.cpp
@@ -996,7 +996,8 @@
         // Use subFormat() to format a repeated pattern character
         // when a different pattern or non-pattern character is seen
         if (ch != prevCh && count > 0) {
-            subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
+            subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++,
+                      prevCh, handler, *workCal, status);
             count = 0;
         }
         if (ch == QUOTE) {
@@ -1023,7 +1024,8 @@
 
     // Format the last item in the pattern, if any
     if (count > 0) {
-        subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
+        subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++,
+                  prevCh, handler, *workCal, status);
     }
 
     if (calClone != NULL) {
@@ -1402,10 +1404,11 @@
 //---------------------------------------------------------------------
 void
 SimpleDateFormat::subFormat(UnicodeString &appendTo,
-                            UChar ch,
+                            char16_t ch,
                             int32_t count,
                             UDisplayContext capitalizationContext,
                             int32_t fieldNum,
+                            char16_t fieldToOutput,
                             FieldPositionHandler& handler,
                             Calendar& cal,
                             UErrorCode& status) const
@@ -1853,8 +1856,11 @@
         // In either case, fall back to am/pm.
         if (toAppend == NULL || toAppend->isBogus()) {
             // Reformat with identical arguments except ch, now changed to 'a'.
-            subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
-                      handler, cal, status);
+            // We are passing a different fieldToOutput because we want to add
+            // 'b' to field position. This makes this fallback stable when
+            // there is a data change on locales.
+            subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'b', handler, cal, status);
+            return;
         } else {
             appendTo += *toAppend;
         }
@@ -1874,9 +1880,11 @@
         if (ruleSet == NULL) {
             // Data doesn't exist for the locale we're looking for.
             // Falling back to am/pm.
-            subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
-                      handler, cal, status);
-            break;
+            // We are passing a different fieldToOutput because we want to add
+            // 'B' to field position. This makes this fallback stable when
+            // there is a data change on locales.
+            subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'B', handler, cal, status);
+            return;
         }
 
         // Get current display time.
@@ -1945,8 +1953,11 @@
         if (periodType == DayPeriodRules::DAYPERIOD_AM ||
             periodType == DayPeriodRules::DAYPERIOD_PM ||
             toAppend->isBogus()) {
-            subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
-                      handler, cal, status);
+            // We are passing a different fieldToOutput because we want to add
+            // 'B' to field position iterator. This makes this fallback stable when
+            // there is a data change on locales.
+            subFormat(appendTo, u'a', count, capitalizationContext, fieldNum, u'B', handler, cal, status);
+            return;
         }
         else {
             appendTo += *toAppend;
@@ -1990,7 +2001,7 @@
     }
 #endif
 
-    handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], beginOffset, appendTo.length());
+    handler.addAttribute(DateFormatSymbols::getPatternCharIndex(fieldToOutput), beginOffset, appendTo.length());
 }
 
 //----------------------------------------------------------------------
diff --git a/icu4c/source/i18n/udateintervalformat.cpp b/icu4c/source/i18n/udateintervalformat.cpp
index d9eaae4..e16df08 100644
--- a/icu4c/source/i18n/udateintervalformat.cpp
+++ b/icu4c/source/i18n/udateintervalformat.cpp
@@ -128,8 +128,27 @@
     }
     auto* resultImpl = UFormattedDateIntervalApiHelper::validate(result, *status);
     DateInterval interval = DateInterval(fromDate,toDate);
-    resultImpl->fImpl = reinterpret_cast<const DateIntervalFormat*>(formatter)
-        ->formatToValue(interval, *status);
+    if (resultImpl != nullptr) {
+        resultImpl->fImpl = reinterpret_cast<const DateIntervalFormat*>(formatter)
+            ->formatToValue(interval, *status);
+    }
+}
+
+U_DRAFT void U_EXPORT2
+udtitvfmt_formatCalendarToResult(
+                const UDateIntervalFormat* formatter,
+                UCalendar*      fromCalendar,
+                UCalendar*      toCalendar,
+                UFormattedDateInterval* result,
+                UErrorCode*     status) {
+    if (U_FAILURE(*status)) {
+        return;
+    }
+    auto* resultImpl = UFormattedDateIntervalApiHelper::validate(result, *status);
+    if (resultImpl != nullptr) {
+        resultImpl->fImpl = reinterpret_cast<const DateIntervalFormat*>(formatter)
+            ->formatToValue(*(Calendar *)fromCalendar, *(Calendar *)toCalendar, *status);
+    }
 }
 
 
diff --git a/icu4c/source/i18n/unicode/numberformatter.h b/icu4c/source/i18n/unicode/numberformatter.h
index 42d4687..58b13c3 100644
--- a/icu4c/source/i18n/unicode/numberformatter.h
+++ b/icu4c/source/i18n/unicode/numberformatter.h
@@ -155,6 +155,8 @@
 class NumberRangeFormatterImpl;
 struct RangeMacroProps;
 struct UFormattedNumberImpl;
+class MutablePatternModifier;
+class ImmutablePatternModifier;
 
 /**
  * Used for NumberRangeFormatter and implemented in numrange_fluent.cpp.
@@ -980,9 +982,13 @@
     friend struct impl::MacroProps;
     friend struct impl::MicroProps;
 
-    // To allow NumberFormatterImpl to access isBogus() and perform other operations:
+    // To allow NumberFormatterImpl to access isBogus():
     friend class impl::NumberFormatterImpl;
 
+    // To allow the use of this class when formatting:
+    friend class impl::MutablePatternModifier;
+    friend class impl::ImmutablePatternModifier;
+
     // So that NumberPropertyMapper can create instances
     friend class impl::NumberPropertyMapper;
 
diff --git a/icu4c/source/i18n/unicode/smpdtfmt.h b/icu4c/source/i18n/unicode/smpdtfmt.h
index 79fa817..b4b0e5f 100644
--- a/icu4c/source/i18n/unicode/smpdtfmt.h
+++ b/icu4c/source/i18n/unicode/smpdtfmt.h
@@ -1274,6 +1274,7 @@
                    int32_t count,
                    UDisplayContext capitalizationContext,
                    int32_t fieldNum,
+                   char16_t fieldToOutput,
                    FieldPositionHandler& handler,
                    Calendar& cal,
                    UErrorCode& status) const; // in case of illegal argument
diff --git a/icu4c/source/i18n/unicode/udateintervalformat.h b/icu4c/source/i18n/unicode/udateintervalformat.h
index b42223a..9777c4b 100644
--- a/icu4c/source/i18n/unicode/udateintervalformat.h
+++ b/icu4c/source/i18n/unicode/udateintervalformat.h
@@ -14,6 +14,7 @@
 
 #if !UCONFIG_NO_FORMATTING
 
+#include "unicode/ucal.h"
 #include "unicode/umisc.h"
 #include "unicode/localpointer.h"
 #include "unicode/uformattedvalue.h"
@@ -278,6 +279,31 @@
                 UDate           fromDate,
                 UDate           toDate,
                 UErrorCode*     status);
+
+/**
+ * Formats a date/time range using the conventions established for the
+ * UDateIntervalFormat object.
+ * @param formatter
+ *            The UDateIntervalFormat object specifying the format conventions.
+ * @param fromCalendar
+ *            The starting point of the range.
+ * @param toCalendar
+ *            The ending point of the range.
+ * @param result
+ *            The UFormattedDateInterval to contain the result of the
+ *            formatting operation.
+ * @param status
+ *            A pointer to a UErrorCode to receive any errors.
+ * @draft ICU 67
+ */
+
+U_DRAFT void U_EXPORT2
+udtitvfmt_formatCalendarToResult(
+                const UDateIntervalFormat* formatter,
+                UCalendar*      fromCalendar,
+                UCalendar*      toCalendar,
+                UFormattedDateInterval* result,
+                UErrorCode*     status);
 #endif /* U_HIDE_DRAFT_API */
 
 
diff --git a/icu4c/source/i18n/unicode/unumberformatter.h b/icu4c/source/i18n/unicode/unumberformatter.h
index b27507f..1d6b460 100644
--- a/icu4c/source/i18n/unicode/unumberformatter.h
+++ b/icu4c/source/i18n/unicode/unumberformatter.h
@@ -336,7 +336,7 @@
 
     /**
      * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a
-     * sign on zero or NaN, unless the sign bit is set (-0.0 gets a sign).
+     * sign on zero, numbers that round to zero, or NaN.
      *
      * @stable ICU 61
      */
@@ -344,9 +344,8 @@
 
     /**
      * Use the locale-dependent accounting format on negative numbers, and show the plus sign on
-     * positive numbers. Do not show a sign on zero or NaN, unless the sign bit is set (-0.0 gets a
-     * sign). For more information on the accounting format, see the ACCOUNTING sign display
-     * strategy.
+     * positive numbers. Do not show a sign on zero, numbers that round to zero, or NaN. For more
+     * information on the accounting format, see the ACCOUNTING sign display strategy.
      *
      * @stable ICU 61
      */
diff --git a/icu4c/source/test/cintltst/cdateintervalformattest.c b/icu4c/source/test/cintltst/cdateintervalformattest.c
index d8a8066..6635de2 100644
--- a/icu4c/source/test/cintltst/cdateintervalformattest.c
+++ b/icu4c/source/test/cintltst/cdateintervalformattest.c
@@ -21,6 +21,7 @@
 static void TestDateIntervalFormat(void);
 static void TestFPos_SkelWithSeconds(void);
 static void TestFormatToResult(void);
+static void TestFormatCalendarToResult(void);
 
 void addDateIntervalFormatTest(TestNode** root);
 
@@ -31,12 +32,15 @@
     TESTCASE(TestDateIntervalFormat);
     TESTCASE(TestFPos_SkelWithSeconds);
     TESTCASE(TestFormatToResult);
+    TESTCASE(TestFormatCalendarToResult);
 }
 
 static const char tzUSPacific[] = "US/Pacific";
 static const char tzAsiaTokyo[] = "Asia/Tokyo";
 #define Date201103021030 1299090600000.0 /* 2011-Mar-02 1030 in US/Pacific, 2011-Mar-03 0330 in Asia/Tokyo */
 #define Date201009270800 1285599629000.0 /* 2010-Sep-27 0800 in US/Pacific */
+#define Date158210140000 -12219379142000.0
+#define Date158210160000 -12219206342000.0
 #define _MINUTE (60.0*1000.0)
 #define _HOUR   (60.0*60.0*1000.0)
 #define _DAY    (24.0*60.0*60.0*1000.0)
@@ -352,7 +356,7 @@
             UPRV_LENGTHOF(expectedFieldPositions));
     }
     {
-        const char* message = "Field position test 1";
+        const char* message = "Field position test 2";
         const UChar* expectedString = u"27. September 2010, 15:00–22:00 Uhr";
         udtitvfmt_formatToResult(fmt, fdi, Date201009270800, Date201009270800 + 7*_HOUR, &ec);
         assertSuccess("Formatting", &ec);
@@ -380,4 +384,144 @@
     udtitvfmt_closeResult(fdi);
 }
 
+static void TestFormatCalendarToResult() {
+    UErrorCode ec = U_ZERO_ERROR;
+    UCalendar* ucal1 = ucal_open(zoneGMT, -1, "de", UCAL_DEFAULT, &ec);
+    ucal_setMillis(ucal1, Date201009270800, &ec);
+    UCalendar* ucal2 = ucal_open(zoneGMT, -1, "de", UCAL_DEFAULT, &ec);
+    ucal_setMillis(ucal2, Date201103021030, &ec);
+    UCalendar* ucal3 = ucal_open(zoneGMT, -1, "de", UCAL_DEFAULT, &ec);
+    ucal_setMillis(ucal3, Date201009270800 + 7*_HOUR, &ec);
+    UCalendar* ucal4 = ucal_open(zoneGMT, -1, "de", UCAL_DEFAULT, &ec);
+    UCalendar* ucal5 = ucal_open(zoneGMT, -1, "de", UCAL_DEFAULT, &ec);
+
+    UDateIntervalFormat* fmt = udtitvfmt_open("de", u"dMMMMyHHmm", -1, zoneGMT, -1, &ec);
+    UFormattedDateInterval* fdi = udtitvfmt_openResult(&ec);
+    assertSuccess("Opening", &ec);
+
+    {
+        const char* message = "Field position test 1";
+        const UChar* expectedString = u"27. September 2010, 15:00 – 2. März 2011, 18:30";
+        udtitvfmt_formatCalendarToResult(fmt, ucal1, ucal2, fdi, &ec);
+        assertSuccess("Formatting", &ec);
+        static const UFieldPositionWithCategory expectedFieldPositions[] = {
+            // category, field, begin index, end index
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 25},
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 2},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 4, 13},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 20, 22},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 23, 25},
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 28, 47},
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 28, 29},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 31, 35},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 36, 40},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 42, 44},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 45, 47}};
+        checkMixedFormattedValue(
+            message,
+            udtitvfmt_resultAsValue(fdi, &ec),
+            expectedString,
+            expectedFieldPositions,
+            UPRV_LENGTHOF(expectedFieldPositions));
+    }
+    {
+        const char* message = "Field position test 2";
+        const UChar* expectedString = u"27. September 2010, 15:00–22:00 Uhr";
+        udtitvfmt_formatCalendarToResult(fmt, ucal1, ucal3, fdi, &ec);
+        assertSuccess("Formatting", &ec);
+        static const UFieldPositionWithCategory expectedFieldPositions[] = {
+            // category, field, begin index, end index
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 2},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 4, 13},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18},
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 20, 25},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 20, 22},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 23, 25},
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 26, 31},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 26, 28},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 29, 31},
+            {UFIELD_CATEGORY_DATE, UDAT_AM_PM_FIELD, 32, 35}};
+        checkMixedFormattedValue(
+            message,
+            udtitvfmt_resultAsValue(fdi, &ec),
+            expectedString,
+            expectedFieldPositions,
+            UPRV_LENGTHOF(expectedFieldPositions));
+    }
+    {
+        const char* message = "Field position test 3";
+        // Date across Julian Gregorian change date.
+        ucal_setMillis(ucal4, Date158210140000, &ec);
+        ucal_setMillis(ucal5, Date158210160000, &ec);
+        //                                        1         2         3         4
+        //                              012345678901234567890123456789012345678901234567890
+        const UChar* expectedString = u"4. Oktober 1582, 00:00 – 16. Oktober 1582, 00:00";
+        udtitvfmt_formatCalendarToResult(fmt, ucal4, ucal5, fdi, &ec);
+        assertSuccess("Formatting", &ec);
+        static const UFieldPositionWithCategory expectedFieldPositions[] = {
+            // category, field, begin index, end index
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 22},
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 1},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 3, 10},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 11, 15},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 17, 19},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 20, 22},
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 25, 48},
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 25, 27},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 29, 36},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 37, 41},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 43, 45},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 46, 48}};
+        checkMixedFormattedValue(
+            message,
+            udtitvfmt_resultAsValue(fdi, &ec),
+            expectedString,
+            expectedFieldPositions,
+            UPRV_LENGTHOF(expectedFieldPositions));
+    }
+    {
+        // Date across Julian Gregorian change date.
+        // We set the Gregorian Change way back.
+        ucal_setGregorianChange(ucal5, (UDate)(-8.64e15), &ec);
+        ucal_setGregorianChange(ucal4, (UDate)(-8.64e15), &ec);
+        ucal_setMillis(ucal4, Date158210140000, &ec);
+        ucal_setMillis(ucal5, Date158210160000, &ec);
+        const char* message = "Field position test 4";
+        //                                        1         2         3         4
+        //                              012345678901234567890123456789012345678901234567890
+        const UChar* expectedString = u"14. Oktober 1582, 00:00 – 16. Oktober 1582, 00:00";
+        udtitvfmt_formatCalendarToResult(fmt, ucal4, ucal5, fdi, &ec);
+        assertSuccess("Formatting", &ec);
+        static const UFieldPositionWithCategory expectedFieldPositions[] = {
+            // category, field, begin index, end index
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 23},
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 2},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 4, 11},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 12, 16},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 18, 20},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 21, 23},
+            {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 26, 49},
+            {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 26, 28},
+            {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 30, 37},
+            {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 38, 42},
+            {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 44, 46},
+            {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 47, 49}};
+        checkMixedFormattedValue(
+            message,
+            udtitvfmt_resultAsValue(fdi, &ec),
+            expectedString,
+            expectedFieldPositions,
+            UPRV_LENGTHOF(expectedFieldPositions));
+    }
+
+    ucal_close(ucal1);
+    ucal_close(ucal2);
+    ucal_close(ucal3);
+    ucal_close(ucal4);
+    ucal_close(ucal5);
+    udtitvfmt_close(fmt);
+    udtitvfmt_closeResult(fdi);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c
index 0a1a0ae..36cd782 100644
--- a/icu4c/source/test/cintltst/cloctst.c
+++ b/icu4c/source/test/cintltst/cloctst.c
@@ -6029,7 +6029,10 @@
     {"aa_BB_CYRL",  "aa-BB-x-lvariant-cyrl", NULL},
     {"en_US_1234",  "en-US-1234",   "en-US-1234"},
     {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb",  "en-US-varianta-variantb"},
-    {"ja__9876_5432",   "ja-9876-5432", "ja-9876-5432"},
+    {"en_US_VARIANTB_VARIANTA", "en-US-varianta-variantb",  "en-US-varianta-variantb"}, /* ICU-20478 */
+    {"ja__9876_5432",   "ja-5432-9876", "ja-5432-9876"}, /* ICU-20478 */
+    {"sl__ROZAJ_BISKE_1994",   "sl-1994-biske-rozaj", "sl-1994-biske-rozaj"}, /* ICU-20478 */
+    {"en__SCOUSE_FONIPA",   "en-fonipa-scouse", "en-fonipa-scouse"}, /* ICU-20478 */
     {"zh_Hant__VAR",    "zh-Hant-x-lvariant-var", NULL},
     {"es__BADVARIANT_GOODVAR",  "es-goodvar",   NULL},
     {"en@calendar=gregorian",   "en-u-ca-gregory",  "en-u-ca-gregory"},
@@ -6187,7 +6190,16 @@
     {"bogus",               "bogus",                FULL_LENGTH},
     {"boguslang",           "",                     0},
     {"EN-lATN-us",          "en_Latn_US",           FULL_LENGTH},
-    {"und-variant-1234",    "__VARIANT_1234",       FULL_LENGTH},
+    {"und-variant-1234",    "__1234_VARIANT",       FULL_LENGTH}, /* ICU-20478 */
+    {"ja-9876-5432",    "ja__5432_9876",       FULL_LENGTH}, /* ICU-20478 */
+    {"en-US-varianta-variantb",    "en_US_VARIANTA_VARIANTB",       FULL_LENGTH}, /* ICU-20478 */
+    {"en-US-variantb-varianta",    "en_US_VARIANTA_VARIANTB",       FULL_LENGTH}, /* ICU-20478 */
+    {"sl-rozaj-1994-biske",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
+    {"sl-biske-1994-rozaj",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
+    {"sl-1994-rozaj-biske",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
+    {"sl-rozaj-biske-1994",    "sl__1994_BISKE_ROZAJ",       FULL_LENGTH}, /* ICU-20478 */
+    {"en-fonipa-scouse",    "en__FONIPA_SCOUSE",       FULL_LENGTH}, /* ICU-20478 */
+    {"en-scouse-fonipa",    "en__FONIPA_SCOUSE",       FULL_LENGTH}, /* ICU-20478 */
     {"und-varzero-var1-vartwo", "__VARZERO",        11},
     {"en-u-ca-gregory",     "en@calendar=gregorian",    FULL_LENGTH},
     {"en-U-cu-USD",         "en@currency=usd",      FULL_LENGTH},
diff --git a/icu4c/source/test/cintltst/cnumtst.c b/icu4c/source/test/cintltst/cnumtst.c
index dbbac08..daeff15 100644
--- a/icu4c/source/test/cintltst/cnumtst.c
+++ b/icu4c/source/test/cintltst/cnumtst.c
@@ -74,6 +74,7 @@
 static void TestSetMaxFracAndRoundIncr(void);
 static void TestIgnorePadding(void);
 static void TestSciNotationMaxFracCap(void);
+static void TestMinIntMinFracZero(void);
 
 #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
 
@@ -114,6 +115,7 @@
     TESTCASE(TestSetMaxFracAndRoundIncr);
     TESTCASE(TestIgnorePadding);
     TESTCASE(TestSciNotationMaxFracCap);
+    TESTCASE(TestMinIntMinFracZero);
 }
 
 /* test Parse int 64 */
@@ -3475,4 +3477,103 @@
     }
 }
 
+static void TestMinIntMinFracZero(void) {
+    UErrorCode status = U_ZERO_ERROR;
+    UNumberFormat* unum = unum_open(UNUM_DECIMAL, NULL, 0, "en_US", NULL, &status);
+    if ( U_FAILURE(status) ) {
+        log_data_err("unum_open UNUM_DECIMAL for en_US fails with %s\n", u_errorName(status));
+    } else {
+        UChar ubuf[kUBufMax];
+        char  bbuf[kBBufMax];
+        int minInt, minFrac, ulen;
+
+        unum_setAttribute(unum, UNUM_MIN_INTEGER_DIGITS, 0);
+        unum_setAttribute(unum, UNUM_MIN_FRACTION_DIGITS, 0);
+        minInt = unum_getAttribute(unum, UNUM_MIN_INTEGER_DIGITS);
+        minFrac = unum_getAttribute(unum, UNUM_MIN_FRACTION_DIGITS);
+        if (minInt != 0 || minFrac != 0) {
+            log_err("after setting minInt=minFrac=0, get minInt %d, minFrac %d\n", minInt, minFrac);
+        }
+
+        ulen = unum_toPattern(unum, FALSE, ubuf, kUBufMax, &status);
+        if ( U_FAILURE(status) ) {
+            log_err("unum_toPattern fails with %s\n", u_errorName(status));
+        } else if (ulen < 3 || u_strstr(ubuf, u"#.#")==NULL) {
+            u_austrncpy(bbuf, ubuf, kUBufMax);
+            log_info("after setting minInt=minFrac=0, expect pattern to contain \"#.#\", but get (%d): \"%s\"\n", ulen, bbuf);
+        }
+
+        status = U_ZERO_ERROR;
+        ulen = unum_formatDouble(unum, 10.0, ubuf, kUBufMax, NULL, &status);
+        if ( U_FAILURE(status) ) {
+            log_err("unum_formatDouble 10.0 ulen %d fails with %s\n", ulen, u_errorName(status));
+        } else if (u_strcmp(ubuf, u"10") != 0) {
+            u_austrncpy(bbuf, ubuf, kUBufMax);
+            log_err("unum_formatDouble 10.0 expected \"10\", got \"%s\"\n", bbuf);
+        }
+
+        status = U_ZERO_ERROR;
+        ulen = unum_formatDouble(unum, 0.9, ubuf, kUBufMax, NULL, &status);
+        if ( U_FAILURE(status) ) {
+            log_err("unum_formatDouble 0.9 ulen %d fails with %s\n", ulen, u_errorName(status));
+        } else if (u_strcmp(ubuf, u".9") != 0) {
+            u_austrncpy(bbuf, ubuf, kUBufMax);
+            log_err("unum_formatDouble 0.9 expected \".9\", got \"%s\"\n", bbuf);
+        }
+
+        status = U_ZERO_ERROR;
+        ulen = unum_formatDouble(unum, 0.0, ubuf, kUBufMax, NULL, &status);
+        if ( U_FAILURE(status) ) {
+            log_err("unum_formatDouble 0.0 ulen %d fails with %s\n", ulen, u_errorName(status));
+        } else if (u_strcmp(ubuf, u"0") != 0) {
+            u_austrncpy(bbuf, ubuf, kUBufMax);
+            log_err("unum_formatDouble 0.0 expected \"0\", got \"%s\"\n", bbuf);
+        }
+
+        unum_close(unum);
+        status = U_ZERO_ERROR;
+        unum = unum_open(UNUM_CURRENCY, NULL, 0, "en_US", NULL, &status);
+        if ( U_FAILURE(status) ) {
+            log_data_err("unum_open UNUM_CURRENCY for en_US fails with %s\n", u_errorName(status));
+        } else {
+            unum_setAttribute(unum, UNUM_MIN_INTEGER_DIGITS, 0);
+            unum_setAttribute(unum, UNUM_MIN_FRACTION_DIGITS, 0);
+            minInt = unum_getAttribute(unum, UNUM_MIN_INTEGER_DIGITS);
+            minFrac = unum_getAttribute(unum, UNUM_MIN_FRACTION_DIGITS);
+            if (minInt != 0 || minFrac != 0) {
+                log_err("after setting CURRENCY minInt=minFrac=0, get minInt %d, minFrac %d\n", minInt, minFrac);
+            }
+
+            status = U_ZERO_ERROR;
+            ulen = unum_formatDouble(unum, 10.0, ubuf, kUBufMax, NULL, &status);
+            if ( U_FAILURE(status) ) {
+                log_err("unum_formatDouble (CURRRENCY) 10.0 ulen %d fails with %s\n", ulen, u_errorName(status));
+            } else if (u_strcmp(ubuf, u"$10") != 0) {
+                u_austrncpy(bbuf, ubuf, kUBufMax);
+                log_err("unum_formatDouble (CURRRENCY) 10.0 expected \"$10\", got \"%s\"\n", bbuf);
+            }
+
+            status = U_ZERO_ERROR;
+            ulen = unum_formatDouble(unum, 0.9, ubuf, kUBufMax, NULL, &status);
+            if ( U_FAILURE(status) ) {
+                log_err("unum_formatDouble (CURRRENCY) 0.9 ulen %d fails with %s\n", ulen, u_errorName(status));
+            } else if (u_strcmp(ubuf, u"$.9") != 0) {
+                u_austrncpy(bbuf, ubuf, kUBufMax);
+                log_err("unum_formatDouble (CURRRENCY) 0.9 expected \"$.9\", got \"%s\"\n", bbuf);
+            }
+
+            status = U_ZERO_ERROR;
+            ulen = unum_formatDouble(unum, 0.0, ubuf, kUBufMax, NULL, &status);
+            if ( U_FAILURE(status) ) {
+                log_err("unum_formatDouble (CURRRENCY) 0.0 ulen %d fails with %s\n", ulen, u_errorName(status));
+            } else if (u_strcmp(ubuf, u"$0") != 0) {
+                u_austrncpy(bbuf, ubuf, kUBufMax);
+                log_err("unum_formatDouble (CURRRENCY) 0.0 expected \"$0\", got \"%s\"\n", bbuf);
+            }
+
+            unum_close(unum);
+        }
+    }
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/dtfmttst.cpp b/icu4c/source/test/intltest/dtfmttst.cpp
index 9684e88..d4fca1c 100644
--- a/icu4c/source/test/intltest/dtfmttst.cpp
+++ b/icu4c/source/test/intltest/dtfmttst.cpp
@@ -128,6 +128,7 @@
     TESTCASE_AUTO(TestDayPeriodParsing);
     TESTCASE_AUTO(TestParseRegression13744);
     TESTCASE_AUTO(TestAdoptCalendarLeak);
+    TESTCASE_AUTO(Test20741_ABFields);
 
     TESTCASE_AUTO_END;
 }
@@ -4912,7 +4913,22 @@
         {Locale::getEnglish(), "jjmm", "h:mm a"},
         {Locale::getEnglish(), "JJmm", "hh:mm"},
         {Locale::getGerman(), "jjmm", "HH:mm"},
-        {Locale::getGerman(), "JJmm", "HH:mm"}
+        {Locale::getGerman(), "JJmm", "HH:mm"},
+        // Ticket #20739
+        {Locale::getEnglish(), "SSSSm", "mm:ss.SSSS"},
+        {Locale::getEnglish(), "mSSSS", "mm:ss.SSSS"},
+        {Locale::getEnglish(), "SSSm", "mm:ss.SSS"},
+        {Locale::getEnglish(), "mSSS", "mm:ss.SSS"},
+        {Locale::getEnglish(), "SSm", "mm:ss.SS"},
+        {Locale::getEnglish(), "mSS", "mm:ss.SS"},
+        {Locale::getEnglish(), "Sm", "mm:ss.S"},
+        {Locale::getEnglish(), "mS", "mm:ss.S"},
+        {Locale::getEnglish(), "S", "S"},
+        {Locale::getEnglish(), "SS", "SS"},
+        {Locale::getEnglish(), "SSS", "SSS"},
+        {Locale::getEnglish(), "SSSS", "SSSS"},
+        {Locale::getEnglish(), "jmsSSS", "h:mm:ss.SSS a"},
+        {Locale::getEnglish(), "jmSSS", "h:mm:ss.SSS a"}
     };
 
     for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
@@ -5555,6 +5571,51 @@
     sdf.adoptCalendar(Calendar::createInstance(status));
 }
 
+/**
+ * Test that 'a' and 'B' fields are not duplicated in the field position iterator.
+ */
+void DateFormatTest::Test20741_ABFields() {
+    IcuTestErrorCode status(*this, "Test20741_ABFields");
+
+    const char16_t timeZone[] = u"PST8PDT";
+
+    UnicodeString skeletons[] = {u"EEEEEBBBBB", u"EEEEEbbbbb"};
+
+    for (int32_t j = 0; j < 2; j++) {
+        UnicodeString skeleton = skeletons[j];
+
+        int32_t count = 0;
+        const Locale* locales = Locale::getAvailableLocales(count);
+        for (int32_t i = 0; i < count; i++) {
+            if (quick && (i % 17) != 0) { continue; }
+
+            const Locale locale = locales[i];
+            LocalPointer<DateTimePatternGenerator> gen(DateTimePatternGenerator::createInstance(locale, status));
+            UnicodeString pattern = gen->getBestPattern(skeleton, status);
+
+            SimpleDateFormat dateFormat(pattern, locale, status);
+            FieldPositionIterator fpositer;
+            UnicodeString result;
+            LocalPointer<Calendar> calendar(Calendar::createInstance(TimeZone::createTimeZone(timeZone), status));
+            calendar->setTime(UDate(0), status);
+            dateFormat.format(*calendar, result, &fpositer, status);
+
+            FieldPosition curFieldPosition;
+            FieldPosition lastFieldPosition;
+            lastFieldPosition.setBeginIndex(-1);
+            lastFieldPosition.setEndIndex(-1);
+            while(fpositer.next(curFieldPosition)) {
+                assertFalse("Field missing on pattern", pattern.indexOf(PATTERN_CHARS[curFieldPosition.getField()]) == -1);
+                if (curFieldPosition.getBeginIndex() == lastFieldPosition.getBeginIndex() && curFieldPosition.getEndIndex() == lastFieldPosition.getEndIndex()) {
+                    assertEquals("Different fields at same position", PATTERN_CHARS[curFieldPosition.getField()], PATTERN_CHARS[lastFieldPosition.getField()]);
+                }
+
+                lastFieldPosition = curFieldPosition;
+            }
+        }
+    }
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 //eof
diff --git a/icu4c/source/test/intltest/dtfmttst.h b/icu4c/source/test/intltest/dtfmttst.h
index fd07b5a..ac36919 100644
--- a/icu4c/source/test/intltest/dtfmttst.h
+++ b/icu4c/source/test/intltest/dtfmttst.h
@@ -263,6 +263,7 @@
     void TestDayPeriodParsing();
     void TestParseRegression13744();
     void TestAdoptCalendarLeak();
+    void Test20741_ABFields();
 
 private:
     UBool showParse(DateFormat &format, const UnicodeString &formattedString);
diff --git a/icu4c/source/test/intltest/loctest.cpp b/icu4c/source/test/intltest/loctest.cpp
index 73f1b73..06fd617 100644
--- a/icu4c/source/test/intltest/loctest.cpp
+++ b/icu4c/source/test/intltest/loctest.cpp
@@ -3156,6 +3156,7 @@
     static const char tag_ill[] = "!";
     static const char tag_no_nul[] = { 'e', 'n', '-', 'G', 'B' };
     static const char tag_ext[] = "en-GB-1-abc-efg-a-xyz";
+    static const char tag_var[] = "sl-rozaj-biske-1994";
 
     static const Locale loc_en("en_US");
     static const Locale loc_oed("en_GB_OXENDICT");
@@ -3163,6 +3164,7 @@
     static const Locale loc_null("");
     static const Locale loc_gb("en_GB");
     static const Locale loc_ext("en_GB@1=abc-efg;a=xyz");
+    static const Locale loc_var("sl__1994_BISKE_ROZAJ");
 
     Locale result_en = Locale::forLanguageTag(tag_en, status);
     status.errIfFailureAndReset("\"%s\"", tag_en);
@@ -3176,6 +3178,10 @@
     status.errIfFailureAndReset("\"%s\"", tag_af);
     assertEquals(tag_af, loc_af.getName(), result_af.getName());
 
+    Locale result_var = Locale::forLanguageTag(tag_var, status);
+    status.errIfFailureAndReset("\"%s\"", tag_var);
+    assertEquals(tag_var, loc_var.getName(), result_var.getName());
+
     Locale result_ill = Locale::forLanguageTag(tag_ill, status);
     assertEquals(tag_ill, U_ILLEGAL_ARGUMENT_ERROR, status.reset());
     assertTrue(result_ill.getName(), result_ill.isBogus());
@@ -3210,12 +3216,14 @@
     static const Locale loc_ext("en@0=abc;a=xyz");
     static const Locale loc_empty("");
     static const Locale loc_ill("!");
+    static const Locale loc_variant("sl__ROZAJ_BISKE_1994");
 
     static const char tag_c[] = "en-US-u-va-posix";
     static const char tag_en[] = "en-US";
     static const char tag_af[] = "af-t-ar-i0-handwrit-u-ca-coptic-x-foo";
     static const char tag_ext[] = "en-0-abc-a-xyz";
     static const char tag_und[] = "und";
+    static const char tag_variant[] = "sl-1994-biske-rozaj";
 
     std::string result;
     StringByteSink<std::string> sink(&result);
@@ -3247,6 +3255,10 @@
     status.errIfFailureAndReset("\"%s\"", loc_ill.getName());
     assertEquals(loc_ill.getName(), tag_und, result_ill.c_str());
 
+    std::string result_variant = loc_variant.toLanguageTag<std::string>(status);
+    status.errIfFailureAndReset("\"%s\"", loc_variant.getName());
+    assertEquals(loc_variant.getName(), tag_variant, result_variant.c_str());
+
     Locale loc_bogus;
     loc_bogus.setToBogus();
     std::string result_bogus = loc_bogus.toLanguageTag<std::string>(status);
diff --git a/icu4c/source/test/intltest/numbertest.h b/icu4c/source/test/intltest/numbertest.h
index 7f5bcdf..adccc9e 100644
--- a/icu4c/source/test/intltest/numbertest.h
+++ b/icu4c/source/test/intltest/numbertest.h
@@ -68,6 +68,7 @@
     // TODO: Add this method if currency symbols override support is added.
     //void symbolsOverride();
     void sign();
+    void signNearZero();
     void signCoverage();
     void decimal();
     void scale();
diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp
index 4e4f0b7..6b4024a 100644
--- a/icu4c/source/test/intltest/numbertest_api.cpp
+++ b/icu4c/source/test/intltest/numbertest_api.cpp
@@ -86,6 +86,7 @@
         // TODO: Add this method if currency symbols override support is added.
         //TESTCASE_AUTO(symbolsOverride);
         TESTCASE_AUTO(sign);
+        TESTCASE_AUTO(signNearZero);
         TESTCASE_AUTO(signCoverage);
         TESTCASE_AUTO(decimal);
         TESTCASE_AUTO(scale);
@@ -1647,7 +1648,7 @@
             u".8765",
             u".08765",
             u".008765",
-            u""); // TODO: Avoid the empty string here?
+            u"0");  // see ICU-20844
 
     assertFormatDescending(
             u"Integer Width Zero Fill 3",
@@ -1694,6 +1695,57 @@
             u"00.008765",
             u"00");
 
+    assertFormatDescending(
+            u"Integer Width Compact",
+            u"compact-short integer-width/000",
+            NumberFormatter::with()
+                .notation(Notation::compactShort())
+                .integerWidth(IntegerWidth::zeroFillTo(3).truncateAt(3)),
+            Locale::getEnglish(),
+            u"088K",
+            u"008.8K",
+            u"876",
+            u"088",
+            u"008.8",
+            u"000.88",
+            u"000.088",
+            u"000.0088",
+            u"000");
+
+    assertFormatDescending(
+            u"Integer Width Scientific",
+            u"scientific integer-width/000",
+            NumberFormatter::with()
+                .notation(Notation::scientific())
+                .integerWidth(IntegerWidth::zeroFillTo(3).truncateAt(3)),
+            Locale::getEnglish(),
+            u"008.765E4",
+            u"008.765E3",
+            u"008.765E2",
+            u"008.765E1",
+            u"008.765E0",
+            u"008.765E-1",
+            u"008.765E-2",
+            u"008.765E-3",
+            u"000E0");
+
+    assertFormatDescending(
+            u"Integer Width Engineering",
+            u"engineering integer-width/000",
+            NumberFormatter::with()
+                .notation(Notation::engineering())
+                .integerWidth(IntegerWidth::zeroFillTo(3).truncateAt(3)),
+            Locale::getEnglish(),
+            u"087.65E3",
+            u"008.765E3",
+            u"876.5E0",
+            u"087.65E0",
+            u"008.765E0",
+            u"876.5E-3",
+            u"087.65E-3",
+            u"008.765E-3",
+            u"000E0");
+
     assertFormatSingle(
             u"Integer Width Remove All A",
             u"integer-width/00",
@@ -2104,6 +2156,49 @@
             u"-444,444.00 US dollars");
 }
 
+void NumberFormatterApiTest::signNearZero() {
+    // https://unicode-org.atlassian.net/browse/ICU-20709
+    IcuTestErrorCode status(*this, "signNearZero");
+    const struct TestCase {
+        UNumberSignDisplay sign;
+        double input;
+        const char16_t* expected;
+    } cases[] = {
+        { UNUM_SIGN_AUTO,  1.1, u"1" },
+        { UNUM_SIGN_AUTO,  0.9, u"1" },
+        { UNUM_SIGN_AUTO,  0.1, u"0" },
+        { UNUM_SIGN_AUTO, -0.1, u"-0" }, // interesting case
+        { UNUM_SIGN_AUTO, -0.9, u"-1" },
+        { UNUM_SIGN_AUTO, -1.1, u"-1" },
+        { UNUM_SIGN_ALWAYS,  1.1, u"+1" },
+        { UNUM_SIGN_ALWAYS,  0.9, u"+1" },
+        { UNUM_SIGN_ALWAYS,  0.1, u"+0" },
+        { UNUM_SIGN_ALWAYS, -0.1, u"-0" },
+        { UNUM_SIGN_ALWAYS, -0.9, u"-1" },
+        { UNUM_SIGN_ALWAYS, -1.1, u"-1" },
+        { UNUM_SIGN_EXCEPT_ZERO,  1.1, u"+1" },
+        { UNUM_SIGN_EXCEPT_ZERO,  0.9, u"+1" },
+        { UNUM_SIGN_EXCEPT_ZERO,  0.1, u"0" }, // interesting case
+        { UNUM_SIGN_EXCEPT_ZERO, -0.1, u"0" }, // interesting case
+        { UNUM_SIGN_EXCEPT_ZERO, -0.9, u"-1" },
+        { UNUM_SIGN_EXCEPT_ZERO, -1.1, u"-1" },
+    };
+    for (auto& cas : cases) {
+        auto sign = cas.sign;
+        auto input = cas.input;
+        auto expected = cas.expected;
+        auto actual = NumberFormatter::with()
+            .sign(sign)
+            .precision(Precision::integer())
+            .locale(Locale::getUS())
+            .formatDouble(input, status)
+            .toString(status);
+        assertEquals(
+            DoubleToUnicodeString(input) + " @ SignDisplay " + Int64ToUnicodeString(sign),
+            expected, actual);
+    }
+}
+
 void NumberFormatterApiTest::signCoverage() {
     // https://unicode-org.atlassian.net/browse/ICU-20708
     IcuTestErrorCode status(*this, "signCoverage");
@@ -2114,7 +2209,7 @@
         { UNUM_SIGN_AUTO, {        u"-∞", u"-1", u"-0",  u"0",  u"1",  u"∞",  u"NaN", u"-NaN" } },
         { UNUM_SIGN_ALWAYS, {      u"-∞", u"-1", u"-0", u"+0", u"+1", u"+∞", u"+NaN", u"-NaN" } },
         { UNUM_SIGN_NEVER, {        u"∞",  u"1",  u"0",  u"0",  u"1",  u"∞",  u"NaN",  u"NaN" } },
-        { UNUM_SIGN_EXCEPT_ZERO, { u"-∞", u"-1", u"-0",  u"0", u"+1", u"+∞",  u"NaN", u"-NaN" } },
+        { UNUM_SIGN_EXCEPT_ZERO, { u"-∞", u"-1",  u"0",  u"0", u"+1", u"+∞",  u"NaN",  u"NaN" } },
     };
     double negNaN = std::copysign(uprv_getNaN(), -0.0);
     const double inputs[] = {
diff --git a/icu4c/source/test/intltest/numbertest_patternmodifier.cpp b/icu4c/source/test/intltest/numbertest_patternmodifier.cpp
index 8f61242..1d1e634 100644
--- a/icu4c/source/test/intltest/numbertest_patternmodifier.cpp
+++ b/icu4c/source/test/intltest/numbertest_patternmodifier.cpp
@@ -41,7 +41,10 @@
     mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false);
     assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
     assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
-    mod.setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
+    mod.setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
+    assertEquals("Pattern a0b", u"-a", getPrefix(mod, status));
+    assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
+    mod.setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
     assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
     assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
     mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false);
@@ -66,7 +69,10 @@
     mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false);
     assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
     assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
-    mod.setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
+    mod.setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
+    assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
+    assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
+    mod.setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
     assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
     assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
     mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false);
@@ -76,9 +82,8 @@
     assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
     assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
     mod.setPatternAttributes(UNUM_SIGN_NEVER, false);
-    // TODO: What should this behavior be?
-    assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
-    assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
+    assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
+    assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
     assertSuccess("Spot 5", status);
 }
 
diff --git a/icu4c/source/test/testdata/numberpermutationtest.txt b/icu4c/source/test/testdata/numberpermutationtest.txt
index b9c8558..4b4656e 100644
--- a/icu4c/source/test/testdata/numberpermutationtest.txt
+++ b/icu4c/source/test/testdata/numberpermutationtest.txt
@@ -2273,15 +2273,15 @@
   es-MX
     0
     +92 k
-    -0
+    0
   zh-TW
     0
     +9萬
-    -0
+    0
   bn-BD

     +৯২ হা
-    -০
+    ০
 
 compact-short .000 sign-accounting-except-zero
   es-MX
@@ -4849,15 +4849,15 @@
   es-MX
     0 %
     +91,827 %
-    -0 %
+    0 %
   zh-TW
     0%
     +91,827%
-    -0%
+    0%
   bn-BD
     ০%
     +৯১,৮২৭%
-    -০%
+    ০%
 
 percent .000 sign-accounting-except-zero
   es-MX
@@ -4905,15 +4905,15 @@
   es-MX
     EUR 0
     +EUR 91,827
-    -EUR 0
+    EUR 0
   zh-TW
     €0
     +€91,827
-    (€0)
+    €0
   bn-BD
     ০€
     +৯১,৮২৭€
-    (০ €)
+    ০€
 
 currency/EUR .000 sign-accounting-except-zero
   es-MX
@@ -4961,15 +4961,15 @@
   es-MX
     0 fur
     +91,827 fur
-    -0 fur
+    0 fur
   zh-TW
     0 化朗
     +91,827 化朗
-    -0 化朗
+    0 化朗
   bn-BD
     ০ ফার্লং
     +৯১,৮২৭ ফার্লং
-    -০ ফার্লং
+    ০ ফার্লং
 
 measure-unit/length-furlong .000 sign-accounting-except-zero
   es-MX
@@ -6627,15 +6627,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD

     +৯১,৮২৭
-    -০
+    ০
 
 unit-width-narrow .000 sign-accounting-except-zero
   es-MX
@@ -6683,15 +6683,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD

     +৯১,৮২৭
-    -০
+    ০
 
 unit-width-full-name .000 sign-accounting-except-zero
   es-MX
@@ -7943,15 +7943,15 @@
   es-MX
     00
     +1827
-    -00
+    00
   zh-TW
     00
     +1,827
-    -00
+    00
   bn-BD
     ০০
     +১,৮২৭
-    -০০
+    ০০
 
 .000 integer-width/##00 sign-accounting-except-zero
   es-MX
@@ -8167,15 +8167,15 @@
   es-MX
     0
     +45,914
-    -0
+    0
   zh-TW
     0
     +45,914
-    -0
+    0
   bn-BD

     +৪৫,৯১৪
-    -০
+    ০
 
 .000 scale/0.5 sign-accounting-except-zero
   es-MX
@@ -8335,15 +8335,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD

     +৯১,৮২৭
-    -০
+    ০
 
 .000 group-on-aligned sign-accounting-except-zero
   es-MX
@@ -8447,15 +8447,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD
     0
     +91,827
-    -0
+    0
 
 .000 latin sign-accounting-except-zero
   es-MX
@@ -8559,15 +8559,15 @@
   es-MX
     0.
     +91,827.
-    -0.
+    0.
   zh-TW
     0.
     +91,827.
-    -0.
+    0.
   bn-BD
     ০.
     +৯১,৮২৭.
-    -০.
+    ০.
 
 .000 sign-accounting-except-zero decimal-always
   es-MX
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java
index 615156b..2a676a36 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java
@@ -9,6 +9,7 @@
 package com.ibm.icu.impl.locale;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -326,7 +327,8 @@
         _script = langtag.getScript();
         _region = langtag.getRegion();
 
-        List<String> bcpVariants = langtag.getVariants();
+        ArrayList<String> bcpVariants = new ArrayList<String>(langtag.getVariants());
+        Collections.sort(bcpVariants);
         if (bcpVariants.size() > 0) {
             StringBuilder var = new StringBuilder(bcpVariants.get(0));
             for (int i = 1; i < bcpVariants.size(); i++) {
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AdoptingModifierStore.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AdoptingModifierStore.java
index 7e3459d..93da08b 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AdoptingModifierStore.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AdoptingModifierStore.java
@@ -3,6 +3,7 @@
 package com.ibm.icu.impl.number;
 
 import com.ibm.icu.impl.StandardPlural;
+import com.ibm.icu.impl.number.Modifier.Signum;
 
 /**
  * This implementation of ModifierStore adopts references to Modifiers.
@@ -11,7 +12,8 @@
  */
 public class AdoptingModifierStore implements ModifierStore {
     private final Modifier positive;
-    private final Modifier zero;
+    private final Modifier posZero;
+    private final Modifier negZero;
     private final Modifier negative;
     final Modifier[] mods;
     boolean frozen;
@@ -22,9 +24,10 @@
      * <p>
      * If this constructor is used, a plural form CANNOT be passed to {@link #getModifier}.
      */
-    public AdoptingModifierStore(Modifier positive, Modifier zero, Modifier negative) {
+    public AdoptingModifierStore(Modifier positive, Modifier posZero, Modifier negZero, Modifier negative) {
         this.positive = positive;
-        this.zero = zero;
+        this.posZero = posZero;
+        this.negZero = negZero;
         this.negative = negative;
         this.mods = null;
         this.frozen = true;
@@ -39,13 +42,14 @@
      */
     public AdoptingModifierStore() {
         this.positive = null;
-        this.zero = null;
+        this.posZero = null;
+        this.negZero = null;
         this.negative = null;
-        this.mods = new Modifier[3 * StandardPlural.COUNT];
+        this.mods = new Modifier[4 * StandardPlural.COUNT];
         this.frozen = false;
     }
 
-    public void setModifier(int signum, StandardPlural plural, Modifier mod) {
+    public void setModifier(Signum signum, StandardPlural plural, Modifier mod) {
         assert !frozen;
         mods[getModIndex(signum, plural)] = mod;
     }
@@ -54,21 +58,34 @@
         frozen = true;
     }
 
-    public Modifier getModifierWithoutPlural(int signum) {
+    public Modifier getModifierWithoutPlural(Signum signum) {
         assert frozen;
         assert mods == null;
-        return signum == 0 ? zero : signum < 0 ? negative : positive;
+        assert signum != null;
+        switch (signum) {
+            case POS:
+                return positive;
+            case POS_ZERO:
+                return posZero;
+            case NEG_ZERO:
+                return negZero;
+            case NEG:
+                return negative;
+            default:
+                throw new AssertionError("Unreachable");
+        }
     }
 
-    public Modifier getModifier(int signum, StandardPlural plural) {
+    @Override
+    public Modifier getModifier(Signum signum, StandardPlural plural) {
         assert frozen;
         assert positive == null;
         return mods[getModIndex(signum, plural)];
     }
 
-    private static int getModIndex(int signum, StandardPlural plural) {
-        assert signum >= -1 && signum <= 1;
+    private static int getModIndex(Signum signum, StandardPlural plural) {
+        assert signum != null;
         assert plural != null;
-        return plural.ordinal() * 3 + (signum + 1);
+        return plural.ordinal() * Signum.COUNT + signum.ordinal();
     }
 }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java
index d551c32..7d30c58 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java
@@ -7,6 +7,7 @@
 import java.text.FieldPosition;
 
 import com.ibm.icu.impl.StandardPlural;
+import com.ibm.icu.impl.number.Modifier.Signum;
 import com.ibm.icu.text.PluralRules;
 import com.ibm.icu.text.UFieldPosition;
 
@@ -130,8 +131,8 @@
     /** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
     public boolean isNegative();
 
-    /** @return -1 if the value is negative; 1 if positive; or 0 if zero. */
-    public int signum();
+    /** @return The appropriate value from the Signum enum. */
+    public Signum signum();
 
     /** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
     @Override
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
index badc530..09c8893 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
@@ -9,6 +9,7 @@
 
 import com.ibm.icu.impl.StandardPlural;
 import com.ibm.icu.impl.Utility;
+import com.ibm.icu.impl.number.Modifier.Signum;
 import com.ibm.icu.text.PluralRules;
 import com.ibm.icu.text.PluralRules.Operand;
 import com.ibm.icu.text.UFieldPosition;
@@ -303,8 +304,18 @@
     }
 
     @Override
-    public int signum() {
-        return isNegative() ? -1 : (isZeroish() && !isInfinite()) ? 0 : 1;
+    public Signum signum() {
+        boolean isZero = (isZeroish() && !isInfinite());
+        boolean isNeg = isNegative();
+        if (isZero && isNeg) {
+            return Signum.NEG_ZERO;
+        } else if (isZero) {
+            return Signum.POS_ZERO;
+        } else if (isNeg) {
+            return Signum.NEG;
+        } else {
+            return Signum.POS;
+        }
     }
 
     @Override
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/LongNameHandler.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/LongNameHandler.java
index c0c6a74..459e514 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/LongNameHandler.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/LongNameHandler.java
@@ -12,6 +12,7 @@
 import com.ibm.icu.impl.SimpleFormatterImpl;
 import com.ibm.icu.impl.StandardPlural;
 import com.ibm.icu.impl.UResource;
+import com.ibm.icu.impl.number.Modifier.Signum;
 import com.ibm.icu.number.NumberFormatter.UnitWidth;
 import com.ibm.icu.text.NumberFormat;
 import com.ibm.icu.text.PluralRules;
@@ -262,7 +263,7 @@
             String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 0, 1);
             Modifier.Parameters parameters = new Modifier.Parameters();
             parameters.obj = this;
-            parameters.signum = 0;
+            parameters.signum = null;// Signum ignored
             parameters.plural = plural;
             modifiers.put(plural, new SimpleModifier(compiled, field, false, parameters));
         }
@@ -281,7 +282,7 @@
                     .compileToStringMinMaxArguments(compoundFormat, sb, 0, 1);
             Modifier.Parameters parameters = new Modifier.Parameters();
             parameters.obj = this;
-            parameters.signum = 0;
+            parameters.signum = null; // Signum ignored
             parameters.plural = plural;
             modifiers.put(plural, new SimpleModifier(compoundCompiled, field, false, parameters));
         }
@@ -296,7 +297,8 @@
     }
 
     @Override
-    public Modifier getModifier(int signum, StandardPlural plural) {
+    public Modifier getModifier(Signum signum, StandardPlural plural) {
+        // Signum ignored
         return modifiers.get(plural);
     }
 }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java
index cc56329..699ba3b 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java
@@ -17,6 +17,15 @@
  */
 public interface Modifier {
 
+    static enum Signum {
+        NEG,
+        NEG_ZERO,
+        POS_ZERO,
+        POS;
+
+        static final int COUNT = Signum.values().length;
+    };
+
     /**
      * Apply this Modifier to the string builder.
      *
@@ -65,7 +74,7 @@
      */
     public static class Parameters {
         public ModifierStore obj;
-        public int signum;
+        public Signum signum;
         public StandardPlural plural;
     }
 
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierStore.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierStore.java
index 1751c1c..2546cf2 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierStore.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/ModifierStore.java
@@ -3,6 +3,7 @@
 package com.ibm.icu.impl.number;
 
 import com.ibm.icu.impl.StandardPlural;
+import com.ibm.icu.impl.number.Modifier.Signum;
 
 /**
  * This is *not* a modifier; rather, it is an object that can return modifiers
@@ -14,5 +15,5 @@
     /**
      * Returns a Modifier with the given parameters (best-effort).
      */
-    Modifier getModifier(int signum, StandardPlural plural);
+    Modifier getModifier(Signum signum, StandardPlural plural);
 }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/MutablePatternModifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/MutablePatternModifier.java
index 67f79b9..2a44151 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/MutablePatternModifier.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/MutablePatternModifier.java
@@ -50,7 +50,7 @@
     PluralRules rules;
 
     // Number details
-    int signum;
+    Signum signum;
     StandardPlural plural;
 
     // QuantityChain details
@@ -129,7 +129,7 @@
      *            The plural form of the number, required only if the pattern contains the triple
      *            currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
      */
-    public void setNumberProperties(int signum, StandardPlural plural) {
+    public void setNumberProperties(Signum signum, StandardPlural plural) {
         assert (plural != null) == needsPlurals();
         this.signum = signum;
         this.plural = plural;
@@ -155,44 +155,35 @@
      * @return An immutable that supports both positive and negative numbers.
      */
     public ImmutablePatternModifier createImmutable() {
-        return createImmutableAndChain(null);
-    }
-
-    /**
-     * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which
-     * is immutable and can be saved for future use. The number properties in the current instance are
-     * mutated; all other properties are left untouched.
-     *
-     * @param parent
-     *            The QuantityChain to which to chain this immutable.
-     * @return An immutable that supports both positive and negative numbers.
-     */
-    public ImmutablePatternModifier createImmutableAndChain(MicroPropsGenerator parent) {
         FormattedStringBuilder a = new FormattedStringBuilder();
         FormattedStringBuilder b = new FormattedStringBuilder();
         if (needsPlurals()) {
             // Slower path when we require the plural keyword.
             AdoptingModifierStore pm = new AdoptingModifierStore();
             for (StandardPlural plural : StandardPlural.VALUES) {
-                setNumberProperties(1, plural);
-                pm.setModifier(1, plural, createConstantModifier(a, b));
-                setNumberProperties(0, plural);
-                pm.setModifier(0, plural, createConstantModifier(a, b));
-                setNumberProperties(-1, plural);
-                pm.setModifier(-1, plural, createConstantModifier(a, b));
+                setNumberProperties(Signum.POS, plural);
+                pm.setModifier(Signum.POS, plural, createConstantModifier(a, b));
+                setNumberProperties(Signum.POS_ZERO, plural);
+                pm.setModifier(Signum.POS_ZERO, plural, createConstantModifier(a, b));
+                setNumberProperties(Signum.NEG_ZERO, plural);
+                pm.setModifier(Signum.NEG_ZERO, plural, createConstantModifier(a, b));
+                setNumberProperties(Signum.NEG, plural);
+                pm.setModifier(Signum.NEG, plural, createConstantModifier(a, b));
             }
             pm.freeze();
-            return new ImmutablePatternModifier(pm, rules, parent);
+            return new ImmutablePatternModifier(pm, rules);
         } else {
             // Faster path when plural keyword is not needed.
-            setNumberProperties(1, null);
+            setNumberProperties(Signum.POS, null);
             Modifier positive = createConstantModifier(a, b);
-            setNumberProperties(0, null);
-            Modifier zero = createConstantModifier(a, b);
-            setNumberProperties(-1, null);
+            setNumberProperties(Signum.POS_ZERO, null);
+            Modifier posZero = createConstantModifier(a, b);
+            setNumberProperties(Signum.NEG_ZERO, null);
+            Modifier negZero = createConstantModifier(a, b);
+            setNumberProperties(Signum.NEG, null);
             Modifier negative = createConstantModifier(a, b);
-            AdoptingModifierStore pm = new AdoptingModifierStore(positive, zero, negative);
-            return new ImmutablePatternModifier(pm, null, parent);
+            AdoptingModifierStore pm = new AdoptingModifierStore(positive, posZero, negZero, negative);
+            return new ImmutablePatternModifier(pm, null);
         }
     }
 
@@ -222,20 +213,30 @@
     public static class ImmutablePatternModifier implements MicroPropsGenerator {
         final AdoptingModifierStore pm;
         final PluralRules rules;
-        final MicroPropsGenerator parent;
+        /* final */ MicroPropsGenerator parent;
 
         ImmutablePatternModifier(
                 AdoptingModifierStore pm,
-                PluralRules rules,
-                MicroPropsGenerator parent) {
+                PluralRules rules) {
             this.pm = pm;
             this.rules = rules;
+            this.parent = null;
+        }
+
+        public ImmutablePatternModifier addToChain(MicroPropsGenerator parent) {
             this.parent = parent;
+            return this;
         }
 
         @Override
         public MicroProps processQuantity(DecimalQuantity quantity) {
             MicroProps micros = parent.processQuantity(quantity);
+            if (micros.rounder != null) {
+                micros.rounder.apply(quantity);
+            }
+            if (micros.modMiddle != null) {
+                return micros;
+            }
             applyToMicros(micros, quantity);
             return micros;
         }
@@ -270,6 +271,12 @@
     @Override
     public MicroProps processQuantity(DecimalQuantity fq) {
         MicroProps micros = parent.processQuantity(fq);
+        if (micros.rounder != null) {
+            micros.rounder.apply(fq);
+        }
+        if (micros.modMiddle != null) {
+            return micros;
+        }
         if (needsPlurals()) {
             StandardPlural pluralForm = RoundingUtils.getPluralSafe(micros.rounder, rules, fq);
             setNumberProperties(fq.signum(), pluralForm);
@@ -367,8 +374,7 @@
         }
         PatternStringUtils.patternInfoToStringBuilder(patternInfo,
                 isPrefix,
-                signum,
-                signDisplay,
+                PatternStringUtils.resolveSignDisplay(signDisplay, signum),
                 plural,
                 perMilleReplacesPercent,
                 currentAffix);
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java
index 26eb457..601f1c8 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java
@@ -5,6 +5,7 @@
 import java.math.BigDecimal;
 
 import com.ibm.icu.impl.StandardPlural;
+import com.ibm.icu.impl.number.Modifier.Signum;
 import com.ibm.icu.impl.number.Padder.PadPosition;
 import com.ibm.icu.number.NumberFormatter.SignDisplay;
 import com.ibm.icu.text.DecimalFormatSymbols;
@@ -14,6 +15,18 @@
  */
 public class PatternStringUtils {
 
+    // Note: the order of fields in this enum matters for parsing.
+    public static enum PatternSignType {
+        // Render using normal positive subpattern rules
+        POS,
+        // Render using rules to force the display of a plus sign
+        POS_SIGN,
+        // Render using negative subpattern rules
+        NEG;
+
+        public static final PatternSignType[] VALUES = PatternSignType.values();
+    };
+
     /**
      * Determine whether a given roundingIncrement should be ignored for formatting
      * based on the current maxFrac value (maximum fraction digits). For example a
@@ -23,7 +36,7 @@
      * it should not be ignored if maxFrac is 2 or more (but a roundingIncrement of
      * 0.005 is treated like 0.001 for significance).
      *
-     * This test is needed for both NumberPropertyMapper.oldToNew and 
+     * This test is needed for both NumberPropertyMapper.oldToNew and
      * PatternStringUtils.propertiesToPatternString, but NumberPropertyMapper
      * is package-private so we have it here.
      *
@@ -416,25 +429,19 @@
     public static void patternInfoToStringBuilder(
             AffixPatternProvider patternInfo,
             boolean isPrefix,
-            int signum,
-            SignDisplay signDisplay,
+            PatternSignType patternSignType,
             StandardPlural plural,
             boolean perMilleReplacesPercent,
             StringBuilder output) {
 
-        // Should the output render '+' where '-' would normally appear in the pattern?
-        boolean plusReplacesMinusSign = signum != -1
-                && (signDisplay == SignDisplay.ALWAYS
-                        || signDisplay == SignDisplay.ACCOUNTING_ALWAYS
-                        || (signum == 1
-                                && (signDisplay == SignDisplay.EXCEPT_ZERO
-                                        || signDisplay == SignDisplay.ACCOUNTING_EXCEPT_ZERO)))
-                && patternInfo.positiveHasPlusSign() == false;
+        boolean plusReplacesMinusSign = (patternSignType == PatternSignType.POS_SIGN)
+                && !patternInfo.positiveHasPlusSign();
 
-        // Should we use the affix from the negative subpattern? (If not, we will use the positive
-        // subpattern.)
+        // Should we use the affix from the negative subpattern?
+        // (If not, we will use the positive subpattern.)
         boolean useNegativeAffixPattern = patternInfo.hasNegativeSubpattern()
-                && (signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
+                && (patternSignType == PatternSignType.NEG
+                    || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
 
         // Resolve the flags for the affix pattern.
         int flags = 0;
@@ -453,8 +460,8 @@
         boolean prependSign;
         if (!isPrefix || useNegativeAffixPattern) {
             prependSign = false;
-        } else if (signum == -1) {
-            prependSign = signDisplay != SignDisplay.NEVER;
+        } else if (patternSignType == PatternSignType.NEG) {
+            prependSign = true;
         } else {
             prependSign = plusReplacesMinusSign;
         }
@@ -483,4 +490,53 @@
         }
     }
 
+    public static PatternSignType resolveSignDisplay(SignDisplay signDisplay, Signum signum) {
+        switch (signDisplay) {
+            case AUTO:
+            case ACCOUNTING:
+                switch (signum) {
+                    case NEG:
+                    case NEG_ZERO:
+                        return PatternSignType.NEG;
+                    case POS_ZERO:
+                    case POS:
+                        return PatternSignType.POS;
+                }
+                break;
+
+            case ALWAYS:
+            case ACCOUNTING_ALWAYS:
+                switch (signum) {
+                    case NEG:
+                    case NEG_ZERO:
+                        return PatternSignType.NEG;
+                    case POS_ZERO:
+                    case POS:
+                        return PatternSignType.POS_SIGN;
+                }
+                break;
+
+            case EXCEPT_ZERO:
+            case ACCOUNTING_EXCEPT_ZERO:
+                switch (signum) {
+                    case NEG:
+                        return PatternSignType.NEG;
+                    case NEG_ZERO:
+                    case POS_ZERO:
+                        return PatternSignType.POS;
+                    case POS:
+                        return PatternSignType.POS_SIGN;
+                }
+                break;
+
+            case NEVER:
+                return PatternSignType.POS;
+
+            default:
+                break;
+        }
+
+        throw new AssertionError("Unreachable");
+    }
+
 }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java
index 0f35a66..7452929 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java
@@ -228,6 +228,9 @@
      */
     public static StandardPlural getPluralSafe(
             Precision rounder, PluralRules rules, DecimalQuantity dq) {
+        if (rounder == null) {
+            return dq.getStandardPlural(rules);
+        }
         // TODO(ICU-20500): Avoid the copy?
         DecimalQuantity copy = dq.createCopy();
         rounder.apply(copy);
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/parse/AffixMatcher.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/parse/AffixMatcher.java
index 4292504..51b8df0 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/parse/AffixMatcher.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/parse/AffixMatcher.java
@@ -12,7 +12,7 @@
 import com.ibm.icu.impl.number.AffixPatternProvider;
 import com.ibm.icu.impl.number.AffixUtils;
 import com.ibm.icu.impl.number.PatternStringUtils;
-import com.ibm.icu.number.NumberFormatter.SignDisplay;
+import com.ibm.icu.impl.number.PatternStringUtils.PatternSignType;
 
 /**
  * @author sffc
@@ -90,20 +90,27 @@
         StringBuilder sb = new StringBuilder();
         ArrayList<AffixMatcher> matchers = new ArrayList<>(6);
         boolean includeUnpaired = 0 != (parseFlags & ParsingUtils.PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES);
-        SignDisplay signDisplay = (0 != (parseFlags & ParsingUtils.PARSE_FLAG_PLUS_SIGN_ALLOWED))
-                ? SignDisplay.ALWAYS
-                : SignDisplay.AUTO;
 
         AffixPatternMatcher posPrefix = null;
         AffixPatternMatcher posSuffix = null;
 
         // Pre-process the affix strings to resolve LDML rules like sign display.
-        for (int signum = 1; signum >= -1; signum--) {
+        for (PatternSignType type : PatternSignType.VALUES) {
+
+            // Skip affixes in some cases
+            if (type == PatternSignType.POS
+                    && 0 != (parseFlags & ParsingUtils.PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
+                continue;
+            }
+            if (type == PatternSignType.POS_SIGN
+                    && 0 == (parseFlags & ParsingUtils.PARSE_FLAG_PLUS_SIGN_ALLOWED)) {
+                continue;
+            }
+
             // Generate Prefix
             PatternStringUtils.patternInfoToStringBuilder(patternInfo,
                     true,
-                    signum,
-                    signDisplay,
+                    type,
                     StandardPlural.OTHER,
                     false,
                     sb);
@@ -113,15 +120,14 @@
             // Generate Suffix
             PatternStringUtils.patternInfoToStringBuilder(patternInfo,
                     false,
-                    signum,
-                    signDisplay,
+                    type,
                     StandardPlural.OTHER,
                     false,
                     sb);
             AffixPatternMatcher suffix = AffixPatternMatcher
                     .fromAffixPattern(sb.toString(), factory, parseFlags);
 
-            if (signum == 1) {
+            if (type == PatternSignType.POS) {
                 posPrefix = prefix;
                 posSuffix = suffix;
             } else if (Objects.equals(prefix, posPrefix) && Objects.equals(suffix, posSuffix)) {
@@ -130,17 +136,17 @@
             }
 
             // Flags for setting in the ParsedNumber; the token matchers may add more.
-            int flags = (signum == -1) ? ParsedNumber.FLAG_NEGATIVE : 0;
+            int flags = (type == PatternSignType.NEG) ? ParsedNumber.FLAG_NEGATIVE : 0;
 
             // Note: it is indeed possible for posPrefix and posSuffix to both be null.
             // We still need to add that matcher for strict mode to work.
             matchers.add(getInstance(prefix, suffix, flags));
             if (includeUnpaired && prefix != null && suffix != null) {
                 // The following if statements are designed to prevent adding two identical matchers.
-                if (signum == 1 || !Objects.equals(prefix, posPrefix)) {
+                if (type == PatternSignType.POS || !Objects.equals(prefix, posPrefix)) {
                     matchers.add(getInstance(prefix, null, flags));
                 }
-                if (signum == 1 || !Objects.equals(suffix, posSuffix)) {
+                if (type == PatternSignType.POS || !Objects.equals(suffix, posSuffix)) {
                     matchers.add(getInstance(null, suffix, flags));
                 }
             }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java b/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java
index a8b704e..a4dad2d 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java
@@ -66,9 +66,10 @@
             CompactType compactType,
             PluralRules rules,
             MutablePatternModifier buildReference,
+            boolean safe,
             MicroPropsGenerator parent) {
         // TODO: Add a data cache? It would be keyed by locale, nsName, compact type, and compact style.
-        return new CompactHandler(this, locale, nsName, compactType, rules, buildReference, parent);
+        return new CompactHandler(this, locale, nsName, compactType, rules, buildReference, safe, parent);
     }
 
     private static class CompactHandler implements MicroPropsGenerator {
@@ -76,6 +77,7 @@
         final PluralRules rules;
         final MicroPropsGenerator parent;
         final Map<String, ImmutablePatternModifier> precomputedMods;
+        final MutablePatternModifier unsafePatternModifier;
         final CompactData data;
 
         private CompactHandler(
@@ -85,6 +87,7 @@
                 CompactType compactType,
                 PluralRules rules,
                 MutablePatternModifier buildReference,
+                boolean safe,
                 MicroPropsGenerator parent) {
             this.rules = rules;
             this.parent = parent;
@@ -94,13 +97,15 @@
             } else {
                 data.populate(notation.compactCustomData);
             }
-            if (buildReference != null) {
+            if (safe) {
                 // Safe code path
                 precomputedMods = new HashMap<>();
                 precomputeAllModifiers(buildReference);
+                unsafePatternModifier = null;
             } else {
                 // Unsafe code path
                 precomputedMods = null;
+                unsafePatternModifier = buildReference;
             }
         }
 
@@ -145,13 +150,14 @@
             } else {
                 // Unsafe code path.
                 // Overwrite the PatternInfo in the existing modMiddle.
-                assert micros.modMiddle instanceof MutablePatternModifier;
                 ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
-                ((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
+                unsafePatternModifier.setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
+                unsafePatternModifier.setNumberProperties(quantity.signum(), null);
+                micros.modMiddle = unsafePatternModifier;
             }
 
             // We already performed rounding. Do not perform it again.
-            micros.rounder = Precision.constructPassThrough();
+            micros.rounder = null;
 
             return micros;
         }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatter.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatter.java
index 497800e..ff0a0a0 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatter.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatter.java
@@ -327,7 +327,7 @@
 
         /**
          * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a
-         * sign on zero or NaN, unless the sign bit is set (-0.0 gets a sign).
+         * sign on zero, numbers that round to zero, or NaN.
          *
          * @stable ICU 61
          * @see NumberFormatter
@@ -336,9 +336,8 @@
 
         /**
          * Use the locale-dependent accounting format on negative numbers, and show the plus sign on
-         * positive numbers. Do not show a sign on zero or NaN, unless the sign bit is set (-0.0 gets a
-         * sign). For more information on the accounting format, see the ACCOUNTING sign display
-         * strategy.
+         * positive numbers. Do not show a sign on zero, numbers that round to zero, or NaN. For more
+         * information on the accounting format, see the ACCOUNTING sign display strategy.
          *
          * @stable ICU 61
          * @see NumberFormatter
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
index 5b772bf..48607c0 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
@@ -17,6 +17,7 @@
 import com.ibm.icu.impl.number.MicroPropsGenerator;
 import com.ibm.icu.impl.number.MultiplierFormatHandler;
 import com.ibm.icu.impl.number.MutablePatternModifier;
+import com.ibm.icu.impl.number.MutablePatternModifier.ImmutablePatternModifier;
 import com.ibm.icu.impl.number.Padder;
 import com.ibm.icu.impl.number.PatternStringParser;
 import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
@@ -97,7 +98,6 @@
      */
     public MicroProps preProcess(DecimalQuantity inValue) {
         MicroProps micros = microPropsGenerator.processQuantity(inValue);
-        micros.rounder.apply(inValue);
         if (micros.integerWidth.maxInt == -1) {
             inValue.setMinInteger(micros.integerWidth.minInt);
         } else {
@@ -111,7 +111,6 @@
         MicroProps micros = new MicroProps(false);
         MicroPropsGenerator microPropsGenerator = macrosToMicroGenerator(macros, micros, false);
         micros = microPropsGenerator.processQuantity(inValue);
-        micros.rounder.apply(inValue);
         if (micros.integerWidth.maxInt == -1) {
             inValue.setMinInteger(micros.integerWidth.minInt);
         } else {
@@ -341,10 +340,9 @@
         } else {
             patternMod.setSymbols(micros.symbols, currency, unitWidth, null);
         }
+        ImmutablePatternModifier immPatternMod = null;
         if (safe) {
-            chain = patternMod.createImmutableAndChain(chain);
-        } else {
-            chain = patternMod.addToChain(chain);
+            immPatternMod = patternMod.createImmutable();
         }
 
         // Outer modifier (CLDR units and currency long names)
@@ -367,8 +365,6 @@
         }
 
         // Compact notation
-        // NOTE: Compact notation can (but might not) override the middle modifier and rounding.
-        // It therefore needs to go at the end of the chain.
         if (macros.notation instanceof CompactNotation) {
             if (rules == null) {
                 // Lazily create PluralRules
@@ -381,10 +377,18 @@
                     micros.nsName,
                     compactType,
                     rules,
-                    safe ? patternMod : null,
+                    patternMod,
+                    safe,
                     chain);
         }
 
+        // Always add the pattern modifier as the last element of the chain.
+        if (safe) {
+            chain = immPatternMod.addToChain(chain);
+        } else {
+            chain = patternMod.addToChain(chain);
+        }
+
         return chain;
     }
 
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/Precision.java b/icu4j/main/classes/core/src/com/ibm/icu/number/Precision.java
index 0aa395f..d8ce8e4 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/Precision.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/Precision.java
@@ -384,8 +384,6 @@
     static final CurrencyRounderImpl MONETARY_STANDARD = new CurrencyRounderImpl(CurrencyUsage.STANDARD);
     static final CurrencyRounderImpl MONETARY_CASH = new CurrencyRounderImpl(CurrencyUsage.CASH);
 
-    static final PassThroughRounderImpl PASS_THROUGH = new PassThroughRounderImpl();
-
     static Precision constructInfinite() {
         return NONE;
     }
@@ -474,10 +472,6 @@
         return returnValue.withMode(base.mathContext);
     }
 
-    static Precision constructPassThrough() {
-        return PASS_THROUGH;
-    }
-
     /**
      * Returns a valid working Rounder. If the Rounder is a CurrencyRounder, applies the given currency.
      * Otherwise, simply passes through the argument.
@@ -713,17 +707,6 @@
         }
     }
 
-    static class PassThroughRounderImpl extends Precision {
-
-        public PassThroughRounderImpl() {
-        }
-
-        @Override
-        public void apply(DecimalQuantity value) {
-            // TODO: Assert that value has already been rounded
-        }
-    }
-
     private static int getRoundingMagnitudeFraction(int maxFrac) {
         if (maxFrac == -1) {
             return Integer.MIN_VALUE;
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/ScientificNotation.java b/icu4j/main/classes/core/src/com/ibm/icu/number/ScientificNotation.java
index 10945cd..e751688 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/ScientificNotation.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/ScientificNotation.java
@@ -196,7 +196,7 @@
             }
 
             // We already performed rounding. Do not perform it again.
-            micros.rounder = Precision.constructPassThrough();
+            micros.rounder = null;
 
             return micros;
         }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/ChineseDateFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/ChineseDateFormat.java
index 735fac6..a101504 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/ChineseDateFormat.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/ChineseDateFormat.java
@@ -126,12 +126,13 @@
                              char ch, int count, int beginOffset,
                              int fieldNum, DisplayContext capitalizationContext,
                              FieldPosition pos,
+                             char patternCharToOutput,
                              Calendar cal) {
 
         // Logic to handle 'G' for chinese calendar is moved into SimpleDateFormat,
         // and obsolete pattern char 'l' is now ignored in SimpleDateFormat, so we
         // just use its implementation
-        super.subFormat(buf, ch, count, beginOffset, fieldNum, capitalizationContext, pos, cal);
+        super.subFormat(buf, ch, count, beginOffset, fieldNum, capitalizationContext, pos, patternCharToOutput, cal);
 
         // The following is no longer an issue for this subclass...
         // TODO: add code to set FieldPosition for 'G' and 'l' fields. This
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DateTimePatternGenerator.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DateTimePatternGenerator.java
index 70c136c..eb23318 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/DateTimePatternGenerator.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DateTimePatternGenerator.java
@@ -2649,6 +2649,25 @@
                 if (subField > 0) subField += value.length();
                 type[field] = subField;
             }
+
+            // #20739, we have a skeleton with milliseconde, but no seconds
+            if (!original.isFieldEmpty(FRACTIONAL_SECOND) && original.isFieldEmpty(SECOND)) {
+                // Force the use of seconds
+                for (int i = 0; i < types.length; ++i) {
+                    int[] row = types[i];
+                    if (row[1] == SECOND) {
+                        // first entry for SECOND
+                        original.populate(SECOND, (char)row[0], row[3]);
+                        baseOriginal.populate(SECOND, (char)row[0], row[3]);
+                        // We add value.length, same as above, when type is first initialized.
+                        // The value we want to "fake" here is "s", and 1 means "s".length()
+                        int subField = row[2];
+                        type[SECOND] = (subField > 0) ? subField + 1 : subField;
+                        break;
+                    }
+                }
+            }
+
             // #13183, handle special behavior for day period characters (a, b, B)
             if (!original.isFieldEmpty(HOUR)) {
                 if (original.getFieldChar(HOUR)=='h' || original.getFieldChar(HOUR)=='K') {
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
index 090e956..733e540 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
@@ -1395,10 +1395,10 @@
                 }
                 if (useFastFormat) {
                     subFormat(toAppendTo, item.type, item.length, toAppendTo.length(),
-                              i, capitalizationContext, pos, cal);
+                              i, capitalizationContext, pos, item.type, cal);
                 } else {
                     toAppendTo.append(subFormat(item.type, item.length, toAppendTo.length(),
-                                                i, capitalizationContext, pos, cal));
+                                                i, capitalizationContext, pos, item.type, cal));
                 }
                 if (attributes != null) {
                     // Check the sub format length
@@ -1547,7 +1547,7 @@
         throws IllegalArgumentException
     {
         // Note: formatData is ignored
-        return subFormat(ch, count, beginOffset, 0, DisplayContext.CAPITALIZATION_NONE, pos, cal);
+        return subFormat(ch, count, beginOffset, 0, DisplayContext.CAPITALIZATION_NONE, pos, ch, cal);
     }
 
      /**
@@ -1561,10 +1561,11 @@
     protected String subFormat(char ch, int count, int beginOffset,
                                int fieldNum, DisplayContext capitalizationContext,
                                FieldPosition pos,
+                               char patternCharToOutput,
                                Calendar cal)
     {
         StringBuffer buf = new StringBuffer();
-        subFormat(buf, ch, count, beginOffset, fieldNum, capitalizationContext, pos, cal);
+        subFormat(buf, ch, count, beginOffset, fieldNum, capitalizationContext, pos, patternCharToOutput, cal);
         return buf.toString();
     }
 
@@ -1586,6 +1587,7 @@
                              char ch, int count, int beginOffset,
                              int fieldNum, DisplayContext capitalizationContext,
                              FieldPosition pos,
+                             char patternCharToOutput,
                              Calendar cal) {
 
         final int maxIntCount = Integer.MAX_VALUE;
@@ -1944,7 +1946,10 @@
             if (toAppend == null) {
                 // Time isn't exactly midnight or noon (as displayed) or localized string doesn't
                 // exist for requested period. Fall back to am/pm instead.
-                subFormat(buf, 'a', count, beginOffset, fieldNum, capitalizationContext, pos, cal);
+                // We are passing a different patternCharToOutput because we want to add
+                // 'b' to field position. This makes this fallback stable when
+                // there is a data change on locales.
+                subFormat(buf, 'a', count, beginOffset, fieldNum, capitalizationContext, pos, 'b', cal);
             } else {
                 buf.append(toAppend);
             }
@@ -1959,8 +1964,11 @@
             if (ruleSet == null) {
                 // Data doesn't exist for the locale we're looking for.
                 // Fall back to am/pm.
-                subFormat(buf, 'a', count, beginOffset, fieldNum, capitalizationContext, pos, cal);
-                break;
+                // We are passing a different patternCharToOutput because we want to add
+                // 'B' to field position. This makes this fallback stable when
+                // there is a data change on locales.
+                subFormat(buf, 'a', count, beginOffset, fieldNum, capitalizationContext, pos, 'B', cal);
+                return;
             }
 
             // Get current display time.
@@ -2025,7 +2033,11 @@
             if (periodType == DayPeriodRules.DayPeriod.AM ||
                     periodType == DayPeriodRules.DayPeriod.PM ||
                     toAppend == null) {
-                subFormat(buf, 'a', count, beginOffset, fieldNum, capitalizationContext, pos, cal);
+                // We are passing a different patternCharToOutput because we want to add
+                // 'B' to field position. This makes this fallback stable when
+                // there is a data change on locales.
+                subFormat(buf, 'a', count, beginOffset, fieldNum, capitalizationContext, pos, 'B', cal);
+                return;
             }
             else {
                 buf.append(toAppend);
@@ -2089,12 +2101,13 @@
         }
 
         // Set the FieldPosition (for the first occurrence only)
+        int outputCharIndex = getIndexFromChar(patternCharToOutput);
         if (pos.getBeginIndex() == pos.getEndIndex()) {
-            if (pos.getField() == PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex]) {
+            if (pos.getField() == PATTERN_INDEX_TO_DATE_FORMAT_FIELD[outputCharIndex]) {
                 pos.setBeginIndex(beginOffset);
                 pos.setEndIndex(beginOffset + buf.length() - bufstart);
             } else if (pos.getFieldAttribute() ==
-                       PATTERN_INDEX_TO_DATE_FORMAT_ATTRIBUTE[patternCharIndex]) {
+                       PATTERN_INDEX_TO_DATE_FORMAT_ATTRIBUTE[outputCharIndex]) {
                 pos.setBeginIndex(beginOffset);
                 pos.setEndIndex(beginOffset + buf.length() - bufstart);
             }
@@ -4368,10 +4381,10 @@
                 PatternItem item = (PatternItem)items[i];
                 if (useFastFormat) {
                     subFormat(appendTo, item.type, item.length, appendTo.length(),
-                              i, capSetting, pos, fromCalendar);
+                              i, capSetting, pos, item.type, fromCalendar);
                 } else {
                     appendTo.append(subFormat(item.type, item.length, appendTo.length(),
-                                              i, capSetting, pos, fromCalendar));
+                                              i, capSetting, pos, item.type, fromCalendar));
                 }
             }
         }
@@ -4386,10 +4399,10 @@
                 PatternItem item = (PatternItem)items[i];
                 if (useFastFormat) {
                     subFormat(appendTo, item.type, item.length, appendTo.length(),
-                              i, capSetting, pos, toCalendar);
+                              i, capSetting, pos, item.type, toCalendar);
                 } else {
                     appendTo.append(subFormat(item.type, item.length, appendTo.length(),
-                                              i, capSetting, pos, toCalendar));
+                                              i, capSetting, pos, item.type, toCalendar));
                 }
             }
         }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java b/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java
index a8d8f7f..06de947 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java
@@ -3246,7 +3246,10 @@
         }
 
         List<String>subtags = tag.getVariants();
-        for (String s : subtags) {
+        // ICU-20478: Sort variants per UTS35.
+        ArrayList<String> variants = new ArrayList<String>(subtags);
+        Collections.sort(variants);
+        for (String s : variants) {
             buf.append(LanguageTag.SEP);
             buf.append(LanguageTag.canonicalizeVariant(s));
         }
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
index 25f7da8..4b4656e 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
@@ -1,4 +1,4 @@
-# © 2017 and later: Unicode, Inc. and others.
+# © 2019 and later: Unicode, Inc. and others.
 # License & terms of use: http://www.unicode.org/copyright.html
 
 compact-short percent unit-width-narrow
@@ -2273,15 +2273,15 @@
   es-MX
     0
     +92 k
-    -0
+    0
   zh-TW
     0
     +9萬
-    -0
+    0
   bn-BD

     +৯২ হা
-    -০
+    ০
 
 compact-short .000 sign-accounting-except-zero
   es-MX
@@ -4849,15 +4849,15 @@
   es-MX
     0 %
     +91,827 %
-    -0 %
+    0 %
   zh-TW
     0%
     +91,827%
-    -0%
+    0%
   bn-BD
     ০%
     +৯১,৮২৭%
-    -০%
+    ০%
 
 percent .000 sign-accounting-except-zero
   es-MX
@@ -4905,15 +4905,15 @@
   es-MX
     EUR 0
     +EUR 91,827
-    -EUR 0
+    EUR 0
   zh-TW
     €0
     +€91,827
-    (€0)
+    €0
   bn-BD
     ০€
     +৯১,৮২৭€
-    (০ €)
+    ০€
 
 currency/EUR .000 sign-accounting-except-zero
   es-MX
@@ -4961,15 +4961,15 @@
   es-MX
     0 fur
     +91,827 fur
-    -0 fur
+    0 fur
   zh-TW
     0 化朗
     +91,827 化朗
-    -0 化朗
+    0 化朗
   bn-BD
     ০ ফার্লং
     +৯১,৮২৭ ফার্লং
-    -০ ফার্লং
+    ০ ফার্লং
 
 measure-unit/length-furlong .000 sign-accounting-except-zero
   es-MX
@@ -6627,15 +6627,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD

     +৯১,৮২৭
-    -০
+    ০
 
 unit-width-narrow .000 sign-accounting-except-zero
   es-MX
@@ -6683,15 +6683,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD

     +৯১,৮২৭
-    -০
+    ০
 
 unit-width-full-name .000 sign-accounting-except-zero
   es-MX
@@ -7943,15 +7943,15 @@
   es-MX
     00
     +1827
-    -00
+    00
   zh-TW
     00
     +1,827
-    -00
+    00
   bn-BD
     ০০
     +১,৮২৭
-    -০০
+    ০০
 
 .000 integer-width/##00 sign-accounting-except-zero
   es-MX
@@ -8167,15 +8167,15 @@
   es-MX
     0
     +45,914
-    -0
+    0
   zh-TW
     0
     +45,914
-    -0
+    0
   bn-BD

     +৪৫,৯১৪
-    -০
+    ০
 
 .000 scale/0.5 sign-accounting-except-zero
   es-MX
@@ -8335,15 +8335,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD

     +৯১,৮২৭
-    -০
+    ০
 
 .000 group-on-aligned sign-accounting-except-zero
   es-MX
@@ -8447,15 +8447,15 @@
   es-MX
     0
     +91,827
-    -0
+    0
   zh-TW
     0
     +91,827
-    -0
+    0
   bn-BD
     0
     +91,827
-    -0
+    0
 
 .000 latin sign-accounting-except-zero
   es-MX
@@ -8559,15 +8559,15 @@
   es-MX
     0.
     +91,827.
-    -0.
+    0.
   zh-TW
     0.
     +91,827.
-    -0.
+    0.
   bn-BD
     ০.
     +৯১,৮২৭.
-    -০.
+    ০.
 
 .000 sign-accounting-except-zero decimal-always
   es-MX
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java
index d8aae25..cb1bc57 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java
@@ -9,6 +9,7 @@
 
 import com.ibm.icu.impl.StandardPlural;
 import com.ibm.icu.impl.number.DecimalQuantity;
+import com.ibm.icu.impl.number.Modifier.Signum;
 import com.ibm.icu.text.PluralRules;
 import com.ibm.icu.text.PluralRules.Operand;
 import com.ibm.icu.text.UFieldPosition;
@@ -517,8 +518,18 @@
   }
 
   @Override
-  public int signum() {
-      return isNegative() ? -1 : isZeroish() ? 0 : 1;
+  public Signum signum() {
+      boolean isZero = (isZeroish() && !isInfinite());
+      boolean isNeg = isNegative();
+      if (isZero && isNeg) {
+          return Signum.NEG_ZERO;
+      } else if (isZero) {
+          return Signum.POS_ZERO;
+      } else if (isNeg) {
+          return Signum.NEG;
+      } else {
+          return Signum.POS;
+      }
   }
 
   private void setNegative(boolean isNegative) {
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java
index f2e3849..42b9ed3 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java
@@ -49,6 +49,7 @@
 import com.ibm.icu.text.DateFormat;
 import com.ibm.icu.text.DateFormat.BooleanAttribute;
 import com.ibm.icu.text.DateFormatSymbols;
+import com.ibm.icu.text.DateTimePatternGenerator;
 import com.ibm.icu.text.DisplayContext;
 import com.ibm.icu.text.NumberFormat;
 import com.ibm.icu.text.SimpleDateFormat;
@@ -5431,4 +5432,67 @@
         dfmt.parse(inDate, pos);
         assertEquals("Error index", inDate.length(), pos.getErrorIndex());
     }
+
+    @Test
+    public void test20739_MillisecondsWithoutSeconds() {
+        String[][] cases = new String[][]{
+            {"SSSSm", "mm:ss.SSSS"},
+            {"mSSSS", "mm:ss.SSSS"},
+            {"SSSm", "mm:ss.SSS"},
+            {"mSSS", "mm:ss.SSS"},
+            {"SSm", "mm:ss.SS"},
+            {"mSS", "mm:ss.SS"},
+            {"Sm", "mm:ss.S"},
+            {"mS", "mm:ss.S"},
+            {"S", "S"},
+            {"SS", "SS"},
+            {"SSS", "SSS"},
+            {"SSSS", "SSSS"},
+            {"jmsSSS", "h:mm:ss.SSS a"},
+            {"jmSSS", "h:mm:ss.SSS a"}
+        };
+
+        ULocale locale = ULocale.ENGLISH;
+        for (String[] cas : cases) {
+            DateFormat fmt = DateFormat.getInstanceForSkeleton( cas[0], locale);
+            String pattern = ((SimpleDateFormat) fmt).toPattern();
+            assertEquals("Format pattern", cas[1], pattern);
+        }
+    }
+
+    @Test
+    public void test20741_ABFields() {
+        String [] skeletons = {"EEEEEBBBBB", "EEEEEbbbbb"};
+        ULocale[] locales = ULocale.getAvailableLocales();
+        for (String skeleton : skeletons) {
+            for (int i = 0; i < locales.length; i++) {
+                ULocale locale = locales[i];
+                if (isQuick() && (i % 17 != 0)) continue;
+
+                DateTimePatternGenerator gen = DateTimePatternGenerator.getInstance(locale);
+                String pattern = gen.getBestPattern(skeleton);
+                SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, locale);
+                Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("PST8PDT"));
+                calendar.setTime(new Date(0));
+
+                FieldPosition pos_c = new FieldPosition(DateFormat.Field.DAY_OF_WEEK);
+                dateFormat.format(calendar, new StringBuffer(""), pos_c);
+                assertFalse("'Day of week' field was not found", pos_c.getBeginIndex() == 0 && pos_c.getEndIndex() == 0);
+
+                if (skeleton.equals("EEEEEBBBBB")) {
+                    FieldPosition pos_B = new FieldPosition(DateFormat.Field.FLEXIBLE_DAY_PERIOD);
+                    dateFormat.format(calendar, new StringBuffer(""), pos_B);
+                    assertFalse("'Flexible day period' field was not found", pos_B.getBeginIndex() == 0 && pos_B.getEndIndex() == 0);
+                } else {
+                    FieldPosition pos_b = new FieldPosition(DateFormat.Field.AM_PM_MIDNIGHT_NOON);
+                    dateFormat.format(calendar, new StringBuffer(""), pos_b);
+                    assertFalse("'AM/PM/Midnight/Noon' field was not found", pos_b.getBeginIndex() == 0 && pos_b.getEndIndex() == 0);
+                }
+
+                FieldPosition pos_a = new FieldPosition(DateFormat.Field.AM_PM);
+                dateFormat.format(calendar, new StringBuffer(""), pos_a);
+                assertTrue("'AM/PM' field was found", pos_a.getBeginIndex() == 0 && pos_a.getEndIndex() == 0);
+            }
+        }
+    }
 }
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MutablePatternModifierTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MutablePatternModifierTest.java
index 9f8585b..180919c 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MutablePatternModifierTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MutablePatternModifierTest.java
@@ -12,6 +12,7 @@
 import com.ibm.icu.impl.number.DecimalQuantity;
 import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
 import com.ibm.icu.impl.number.MicroProps;
+import com.ibm.icu.impl.number.Modifier.Signum;
 import com.ibm.icu.impl.number.MutablePatternModifier;
 import com.ibm.icu.impl.number.PatternStringParser;
 import com.ibm.icu.number.NumberFormatter.SignDisplay;
@@ -32,19 +33,22 @@
                 UnitWidth.SHORT,
                 null);
 
-        mod.setNumberProperties(1, null);
+        mod.setNumberProperties(Signum.POS, null);
         assertEquals("a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
         mod.setPatternAttributes(SignDisplay.ALWAYS, false);
         assertEquals("+a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
-        mod.setNumberProperties(0, null);
+        mod.setNumberProperties(Signum.POS_ZERO, null);
         assertEquals("+a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
+        mod.setNumberProperties(Signum.NEG_ZERO, null);
+        assertEquals("-a", getPrefix(mod));
+        assertEquals("b", getSuffix(mod));
         mod.setPatternAttributes(SignDisplay.EXCEPT_ZERO, false);
         assertEquals("a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
-        mod.setNumberProperties(-1, null);
+        mod.setNumberProperties(Signum.NEG, null);
         assertEquals("-a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
         mod.setPatternAttributes(SignDisplay.NEVER, false);
@@ -53,24 +57,27 @@
 
         mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"), null);
         mod.setPatternAttributes(SignDisplay.AUTO, false);
-        mod.setNumberProperties(1, null);
+        mod.setNumberProperties(Signum.POS, null);
         assertEquals("a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
         mod.setPatternAttributes(SignDisplay.ALWAYS, false);
         assertEquals("c+", getPrefix(mod));
         assertEquals("d", getSuffix(mod));
-        mod.setNumberProperties(0, null);
+        mod.setNumberProperties(Signum.POS_ZERO, null);
         assertEquals("c+", getPrefix(mod));
         assertEquals("d", getSuffix(mod));
+        mod.setNumberProperties(Signum.NEG_ZERO, null);
+        assertEquals("c-", getPrefix(mod));
+        assertEquals("d", getSuffix(mod));
         mod.setPatternAttributes(SignDisplay.EXCEPT_ZERO, false);
         assertEquals("a", getPrefix(mod));
         assertEquals("b", getSuffix(mod));
-        mod.setNumberProperties(-1, null);
+        mod.setNumberProperties(Signum.NEG, null);
         assertEquals("c-", getPrefix(mod));
         assertEquals("d", getSuffix(mod));
         mod.setPatternAttributes(SignDisplay.NEVER, false);
-        assertEquals("c-", getPrefix(mod)); // TODO: What should this behavior be?
-        assertEquals("d", getSuffix(mod));
+        assertEquals("a", getPrefix(mod));
+        assertEquals("b", getSuffix(mod));
     }
 
     @Test
@@ -112,7 +119,7 @@
                 Currency.getInstance("USD"),
                 UnitWidth.SHORT,
                 null);
-        mod.setNumberProperties(1, null);
+        mod.setNumberProperties(Signum.POS_ZERO, null);
 
         // Unsafe Code Path
         FormattedStringBuilder nsb = new FormattedStringBuilder();
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
index e5a872c..a12468f 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
@@ -1625,6 +1625,57 @@
                 "00.008765",
                 "00");
 
+        assertFormatDescending(
+                "Integer Width Compact",
+                "compact-short integer-width/000",
+                NumberFormatter.with()
+                    .notation(Notation.compactShort())
+                    .integerWidth(IntegerWidth.zeroFillTo(3).truncateAt(3)),
+                ULocale.ENGLISH,
+                "088K",
+                "008.8K",
+                "876",
+                "088",
+                "008.8",
+                "000.88",
+                "000.088",
+                "000.0088",
+                "000");
+
+        assertFormatDescending(
+                "Integer Width Scientific",
+                "scientific integer-width/000",
+                NumberFormatter.with()
+                    .notation(Notation.scientific())
+                    .integerWidth(IntegerWidth.zeroFillTo(3).truncateAt(3)),
+                ULocale.ENGLISH,
+                "008.765E4",
+                "008.765E3",
+                "008.765E2",
+                "008.765E1",
+                "008.765E0",
+                "008.765E-1",
+                "008.765E-2",
+                "008.765E-3",
+                "000E0");
+
+        assertFormatDescending(
+                "Integer Width Engineering",
+                "engineering integer-width/000",
+                NumberFormatter.with()
+                    .notation(Notation.engineering())
+                    .integerWidth(IntegerWidth.zeroFillTo(3).truncateAt(3)),
+                ULocale.ENGLISH,
+                "087.65E3",
+                "008.765E3",
+                "876.5E0",
+                "087.65E0",
+                "008.765E0",
+                "876.5E-3",
+                "087.65E-3",
+                "008.765E-3",
+                "000E0");
+
         assertFormatSingle(
                 "Integer Width Remove All A",
                 "integer-width/00",
@@ -2030,13 +2081,52 @@
     }
 
     @Test
+    public void signNearZero() {
+        // https://unicode-org.atlassian.net/browse/ICU-20709
+        Object[][] cases = {
+            { SignDisplay.AUTO,  1.1, "1" },
+            { SignDisplay.AUTO,  0.9, "1" },
+            { SignDisplay.AUTO,  0.1, "0" },
+            { SignDisplay.AUTO, -0.1, "-0" }, // interesting case
+            { SignDisplay.AUTO, -0.9, "-1" },
+            { SignDisplay.AUTO, -1.1, "-1" },
+            { SignDisplay.ALWAYS,  1.1, "+1" },
+            { SignDisplay.ALWAYS,  0.9, "+1" },
+            { SignDisplay.ALWAYS,  0.1, "+0" },
+            { SignDisplay.ALWAYS, -0.1, "-0" },
+            { SignDisplay.ALWAYS, -0.9, "-1" },
+            { SignDisplay.ALWAYS, -1.1, "-1" },
+            { SignDisplay.EXCEPT_ZERO,  1.1, "+1" },
+            { SignDisplay.EXCEPT_ZERO,  0.9, "+1" },
+            { SignDisplay.EXCEPT_ZERO,  0.1, "0" }, // interesting case
+            { SignDisplay.EXCEPT_ZERO, -0.1, "0" }, // interesting case
+            { SignDisplay.EXCEPT_ZERO, -0.9, "-1" },
+            { SignDisplay.EXCEPT_ZERO, -1.1, "-1" },
+        };
+        for (Object[] cas : cases) {
+            SignDisplay sign = (SignDisplay) cas[0];
+            double input = (Double) cas[1];
+            String expected = (String) cas[2];
+            String actual = NumberFormatter.with()
+                .sign(sign)
+                .precision(Precision.integer())
+                .locale(Locale.US)
+                .format(input)
+                .toString();
+            assertEquals(
+                input + " @ SignDisplay " + sign,
+                expected, actual);
+        }
+    }
+
+    @Test
     public void signCoverage() {
         // https://unicode-org.atlassian.net/browse/ICU-20708
         Object[][][] cases = new Object[][][] {
             { {SignDisplay.AUTO}, { "-∞", "-1", "-0", "0", "1", "∞", "NaN", "-NaN" } },
             { {SignDisplay.ALWAYS}, { "-∞", "-1", "-0", "+0", "+1", "+∞", "+NaN", "-NaN" } },
             { {SignDisplay.NEVER}, { "∞", "1", "0", "0", "1", "∞", "NaN", "NaN" } },
-            { {SignDisplay.EXCEPT_ZERO}, { "-∞", "-1", "-0", "0", "+1", "+∞", "NaN", "-NaN" } },
+            { {SignDisplay.EXCEPT_ZERO}, { "-∞", "-1", "0", "0", "+1", "+∞", "NaN", "NaN" } },
         };
         double negNaN = Math.copySign(Double.NaN, -0.0);
         double inputs[] = new double[] {
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberPermutationTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberPermutationTest.java
index 3ce326f..d7056b9 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberPermutationTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberPermutationTest.java
@@ -96,7 +96,7 @@
 
         // Build up the golden data string as we evaluate all permutations
         ArrayList<String> resultLines = new ArrayList<>();
-        resultLines.add("# © 2017 and later: Unicode, Inc. and others.");
+        resultLines.add("# © 2019 and later: Unicode, Inc. and others.");
         resultLines.add("# License & terms of use: http://www.unicode.org/copyright.html");
         resultLines.add("");
 
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java
index fc2dc4f..4c4ba97 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ULocaleTest.java
@@ -4106,8 +4106,8 @@
                 {"aa_BB_CYRL",  "aa-BB-x-lvariant-cyrl"},
                 {"en_US_1234",  "en-US-1234"},
                 {"en_US_VARIANTA_VARIANTB", "en-US-varianta-variantb"},
-                {"en_US_VARIANTB_VARIANTA", "en-US-variantb-varianta"},
-                {"ja__9876_5432",   "ja-9876-5432"},
+                {"en_US_VARIANTB_VARIANTA", "en-US-varianta-variantb"}, /* ICU-20478 */
+                {"ja__9876_5432",   "ja-5432-9876"}, /* ICU-20478 */
                 {"zh_Hant__VAR",    "zh-Hant-x-lvariant-var"},
                 {"es__BADVARIANT_GOODVAR",  "es"},
                 {"es__GOODVAR_BAD_BADVARIANT",  "es-goodvar-x-lvariant-bad"},
@@ -4131,6 +4131,9 @@
                 {"en@a=bar;attribute=baz;calendar=islamic-civil;x=u-foo",   "en-a-bar-u-baz-ca-islamic-civil-x-u-foo"},
                 /* ICU-20320*/
                 {"en@9=efg;a=baz",   "en-9-efg-a-baz"},
+                /* ICU-20478 */
+                {"sl__ROZAJ_BISKE_1994",   "sl-1994-biske-rozaj"},
+                {"en__SCOUSE_FONIPA",   "en-fonipa-scouse"},
         };
 
         for (int i = 0; i < locale_to_langtag.length; i++) {
@@ -4228,7 +4231,7 @@
                 {"bogus",               "bogus",                NOERROR},
                 {"boguslang",           "",                     Integer.valueOf(0)},
                 {"EN-lATN-us",          "en_Latn_US",           NOERROR},
-                {"und-variant-1234",    "__VARIANT_1234",       NOERROR},
+                {"und-variant-1234",    "__1234_VARIANT",       NOERROR}, /* ICU-20478 */
                 {"und-varzero-var1-vartwo", "__VARZERO",        Integer.valueOf(12)},
                 {"en-u-ca-gregory",     "en@calendar=gregorian",    NOERROR},
                 {"en-U-cu-USD",         "en@currency=usd",      NOERROR},
@@ -4274,6 +4277,16 @@
                 /* #20410 */
                 {"art-lojban-x-0", "jbo@x=0", NOERROR},
                 {"zh-xiang-u-nu-thai-x-0", "hsn@numbers=thai;x=0", NOERROR},
+                /* ICU-20478 */
+                {"ja-9876-5432",    "ja__5432_9876",       NOERROR},
+                {"en-US-variantb-varianta",    "en_US_VARIANTA_VARIANTB",       NOERROR},
+                {"en-US-varianta-variantb",    "en_US_VARIANTA_VARIANTB",       NOERROR},
+                {"sl-rozaj-biske-1994",    "sl__1994_BISKE_ROZAJ",       NOERROR},
+                {"sl-biske-rozaj-1994",    "sl__1994_BISKE_ROZAJ",       NOERROR},
+                {"sl-biske-1994-rozaj",    "sl__1994_BISKE_ROZAJ",       NOERROR},
+                {"sl-1994-biske-rozaj",    "sl__1994_BISKE_ROZAJ",       NOERROR},
+                {"en-fonipa-scouse",    "en__FONIPA_SCOUSE",       NOERROR},
+                {"en-scouse-fonipa",    "en__FONIPA_SCOUSE",       NOERROR},
         };
 
         for (int i = 0; i < langtag_to_locale.length; i++) {