如何找到与给定的 LocalDateTime 和 ZoneId 对应的所有 Instants?
How to find all Instants which correspond to the given LocalDateTime and ZoneId?
在将Instant
转换为LocalDateTime
时,可能会出现几个不同的Instant
转换为相同的LocalDateTime
的情况。例如。在有夏令时的时区。
我的问题是是否可以编写一个适用于任何 ZoneId
和 LocalDateTime
以及 returns 所有 Instant
在给定时间内的通用函数映射到给定 LocalDateTime
:
的区域
List<Instant> localToInstants(LocalDateTime dt, ZoneId zone)
对于任何给定的一对 LocalDateTime
和 ZoneId
,只有一个 Instant
- 因为 Instant
是 UTC 偏移量的时刻,+0:0 .
您可能正在寻找从 LocalDateTime
到 List<OffsetDateTime>
的转换,其编码如下:
List<OffsetDateTime> localToOffsets(LocalDateTime ldt, ZoneId zone) {
ZoneRules rules = zone.getRules();
return rules.getValidOffsets(ldt).stream()
.map(ldt::atOffset)
.collect(Collectors.toList());
}
循环所有时区,将每个时区指定为您的 LocalDateTime
. From each ZonedDateTime
object produced you can extract an Instant
的上下文。其中一些 Instant
对象将代表同一时刻,其中各个时区碰巧在该日期和时间共享相同的距 UTC 的偏移量。
在此示例代码中,我们从特定的 LocalDateTime
开始。这意味着日期带有一天中的时间——在没有时区或与 UTC 的偏移量的情况下本质上是模棱两可的。我们将 LocalDateTime
重复放置在这样的上下文中,放置在 ZonedDateTime
对象的 tzdata within our version of Java. The result of placing LocalDateTime
in a ZoneId
is a ZonedDateTime
. We then extract an Instant
, effectively adjusting to UTC as Instant
is a moment as seen in UTC. We put the Instant
object into a Map
as the key. For the value of the map, we have a collection of ZonedDateTime
objects that report that same instant. So we have a multimap, a map of key Instant
to multiple values, a Set
已知的每个时区中。
LocalDateTime myLocalDateTime = LocalDateTime.of( 2021 , Month.MARCH , 23 , 15 , 30 , 0 , 0 );
Set < String > zoneNames = ZoneId.getAvailableZoneIds();
NavigableMap < Instant, NavigableSet < ZonedDateTime > > instantToZdts = new TreeMap <>();
for ( String zoneName : zoneNames )
{
ZoneId z = ZoneId.of( zoneName );
ZonedDateTime zdt = myLocalDateTime.atZone( z );
Instant instant = zdt.toInstant();
//System.out.println( myLocalDateTime + " in " + z + " is " + zdt + " = " + instant );
instantToZdts.putIfAbsent( instant , new TreeSet <>() );
instantToZdts.get( instant ).add( zdt );
}
向控制台报告结果。
System.out.println( "instantToZdts = " + instantToZdts );
System.out.println( "---------------| " + myLocalDateTime + " |-----------------------" );
System.out.println( "" ) ;
for ( Instant instant : instantToZdts.keySet() )
{
Set < ZoneId > zoneIds = instantToZdts.get( instant ).stream().map( zonedDateTime -> zonedDateTime.getZone() ).collect( Collectors.toSet() );
System.out.println( "Instant: " + instant + " in: " + zoneIds );
System.out.println( "" );
}
当运行.
---------------| 2021-03-23T15:30 |-----------------------
Instant: 2021-03-23T01:30:00Z in: [Pacific/Apia, Pacific/Kiritimati, Etc/GMT-14]
Instant: 2021-03-23T01:45:00Z in: [Pacific/Chatham, NZ-CHAT]
Instant: 2021-03-23T02:30:00Z in: [Antarctica/McMurdo, Pacific/Tongatapu, Pacific/Enderbury, Pacific/Fakaofo, NZ, Antarctica/South_Pole, Pacific/Auckland, Etc/GMT-13]
Instant: 2021-03-23T03:30:00Z in: [Pacific/Funafuti, Pacific/Norfolk, Etc/GMT-12, Asia/Kamchatka, Pacific/Tarawa, Kwajalein, Pacific/Kwajalein, Asia/Anadyr, Pacific/Majuro, Pacific/Wake, Pacific/Nauru, Pacific/Fiji, Pacific/Wallis]
Instant: 2021-03-23T04:30:00Z in: [Australia/Sydney, Australia/LHI, Pacific/Efate, Asia/Magadan, Antarctica/Casey, Antarctica/Macquarie, Australia/Lord_Howe, Australia/Victoria, Etc/GMT-11, Pacific/Bougainville, Asia/Srednekolymsk, Australia/Tasmania, Australia/Currie, Pacific/Pohnpei, Australia/Melbourne, Pacific/Noumea, Australia/Hobart, Pacific/Guadalcanal, Pacific/Ponape, Australia/ACT, Australia/Canberra, Australia/NSW, Pacific/Kosrae, Asia/Sakhalin]
Instant: 2021-03-23T05:00:00Z in: [Australia/Adelaide, Australia/South, Australia/Broken_Hill, Australia/Yancowinna]
Instant: 2021-03-23T05:30:00Z in: [Pacific/Port_Moresby, Asia/Vladivostok, Pacific/Saipan, Asia/Ust-Nera, Antarctica/DumontDUrville, Etc/GMT-10, Pacific/Truk, Australia/Lindeman, Pacific/Chuuk, Australia/Brisbane, Pacific/Guam, Pacific/Yap, Australia/Queensland]
Instant: 2021-03-23T06:00:00Z in: [Australia/North, Australia/Darwin]
Instant: 2021-03-23T06:30:00Z in: [Asia/Pyongyang, Asia/Tokyo, Asia/Yakutsk, Asia/Jayapura, Asia/Dili, Japan, Asia/Khandyga, Pacific/Palau, Asia/Chita, Etc/GMT-9, Asia/Seoul, ROK]
Instant: 2021-03-23T06:45:00Z in: [Australia/Eucla]
Instant: 2021-03-23T07:30:00Z in: [PRC, Singapore, Hongkong, Asia/Hong_Kong, Asia/Taipei, Asia/Ulan_Bator, Asia/Manila, Asia/Irkutsk, Asia/Ujung_Pandang, Asia/Harbin, Asia/Kuching, Asia/Chongqing, Australia/Perth, Asia/Kuala_Lumpur, Asia/Ulaanbaatar, Asia/Chungking, Asia/Macao, Asia/Shanghai, Asia/Brunei, Asia/Macau, Asia/Choibalsan, Australia/West, Asia/Singapore, Asia/Makassar, Etc/GMT-8]
Instant: 2021-03-23T08:30:00Z in: [Asia/Vientiane, Asia/Ho_Chi_Minh, Asia/Tomsk, Asia/Phnom_Penh, Asia/Jakarta, Asia/Hovd, Asia/Barnaul, Asia/Krasnoyarsk, Asia/Pontianak, Asia/Bangkok, Asia/Saigon, Asia/Novokuznetsk, Asia/Novosibirsk, Indian/Christmas, Antarctica/Davis, Etc/GMT-7]
Instant: 2021-03-23T09:00:00Z in: [Asia/Yangon, Indian/Cocos, Asia/Rangoon]
Instant: 2021-03-23T09:30:00Z in: [Asia/Dacca, Asia/Thimbu, Asia/Omsk, Asia/Qostanay, Asia/Almaty, Asia/Dhaka, Indian/Chagos, Asia/Kashgar, Asia/Urumqi, Antarctica/Vostok, Asia/Bishkek, Asia/Thimphu, Etc/GMT-6]
Instant: 2021-03-23T09:45:00Z in: [Asia/Katmandu, Asia/Kathmandu]
Instant: 2021-03-23T10:00:00Z in: [Asia/Calcutta, Asia/Colombo, Asia/Kolkata]
Instant: 2021-03-23T10:30:00Z in: [Asia/Aqtobe, Asia/Samarkand, Indian/Kerguelen, Asia/Oral, Asia/Ashgabat, Asia/Dushanbe, Asia/Aqtau, Asia/Ashkhabad, Asia/Tashkent, Antarctica/Mawson, Asia/Karachi, Asia/Atyrau, Asia/Yekaterinburg, Etc/GMT-5, Asia/Qyzylorda, Indian/Maldives]
Instant: 2021-03-23T11:00:00Z in: [Asia/Kabul, Asia/Tehran, Iran]
Instant: 2021-03-23T11:30:00Z in: [Indian/Mahe, Indian/Mauritius, Europe/Astrakhan, Indian/Reunion, Asia/Yerevan, Europe/Ulyanovsk, Asia/Dubai, Asia/Muscat, Asia/Tbilisi, Europe/Samara, Europe/Saratov, Europe/Volgograd, Etc/GMT-4, Asia/Baku]
Instant: 2021-03-23T12:30:00Z in: [Asia/Aden, Asia/Qatar, Africa/Nairobi, Antarctica/Syowa, Africa/Juba, Asia/Riyadh, Europe/Moscow, Asia/Bahrain, Africa/Mogadishu, Africa/Dar_es_Salaam, Asia/Baghdad, Asia/Kuwait, Africa/Addis_Ababa, Asia/Istanbul, Africa/Djibouti, Europe/Kirov, Africa/Asmara, Africa/Asmera, Europe/Simferopol, Indian/Antananarivo, Africa/Kampala, Indian/Mayotte, W-SU, Turkey, Europe/Istanbul, Etc/GMT-3, Indian/Comoro, Europe/Minsk]
Instant: 2021-03-23T13:30:00Z in: [Europe/Kiev, Asia/Hebron, Egypt, Europe/Zaporozhye, Asia/Nicosia, Africa/Lusaka, Africa/Gaborone, Africa/Maputo, Europe/Kaliningrad, Libya, Africa/Cairo, Africa/Windhoek, Europe/Mariehamn, Africa/Mbabane, Europe/Vilnius, Asia/Gaza, Europe/Chisinau, Asia/Famagusta, Africa/Maseru, Asia/Amman, Africa/Lubumbashi, Europe/Bucharest, Europe/Uzhgorod, Europe/Helsinki, Asia/Beirut, Africa/Harare, Asia/Tel_Aviv, Africa/Kigali, Europe/Sofia, Europe/Tallinn, Africa/Khartoum, EET, Europe/Tiraspol, Africa/Johannesburg, Europe/Nicosia, Asia/Damascus, Africa/Bujumbura, Asia/Jerusalem, Europe/Athens, Africa/Tripoli, Etc/GMT-2, Israel, Africa/Blantyre, Europe/Riga]
Instant: 2021-03-23T14:30:00Z in: [Europe/Ljubljana, Africa/Libreville, Europe/Berlin, Africa/El_Aaiun, Europe/Oslo, Europe/Stockholm, Europe/Budapest, Europe/Bratislava, Europe/San_Marino, Europe/Zagreb, Europe/Copenhagen, Europe/Malta, Europe/Brussels, Europe/Vienna, Africa/Douala, Europe/Busingen, Europe/Warsaw, CET, Africa/Malabo, Etc/GMT-1, Europe/Podgorica, Europe/Skopje, Europe/Paris, Africa/Ndjamena, Europe/Sarajevo, Europe/Tirane, Africa/Bangui, Europe/Luxembourg, Europe/Belgrade, Arctic/Longyearbyen, MET, Africa/Casablanca, Africa/Lagos, Europe/Rome, Africa/Brazzaville, Africa/Luanda, Africa/Porto-Novo, Atlantic/Jan_Mayen, Africa/Ceuta, Africa/Algiers, Europe/Zurich, Europe/Amsterdam, Poland, Europe/Vatican, Europe/Gibraltar, Africa/Kinshasa, Europe/Madrid, Europe/Vaduz, Africa/Niamey, Europe/Prague, Africa/Tunis, Europe/Andorra, Europe/Monaco]
Instant: 2021-03-23T15:30:00Z in: [UTC, UCT, Portugal, Iceland, Zulu, Africa/Ouagadougou, Europe/Lisbon, Etc/Universal, Europe/London, Atlantic/Faeroe, Africa/Dakar, Etc/GMT, Atlantic/Canary, Africa/Lome, Universal, Africa/Freetown, Africa/Sao_Tome, GMT, Greenwich, Etc/GMT-0, Europe/Jersey, GB-Eire, Africa/Bissau, Europe/Belfast, Africa/Abidjan, Atlantic/Reykjavik, Africa/Monrovia, WET, Atlantic/St_Helena, Etc/Greenwich, Etc/GMT0, Africa/Bamako, Eire, Europe/Guernsey, Africa/Timbuktu, Atlantic/Madeira, GB, Africa/Accra, Africa/Conakry, Atlantic/Faroe, Etc/UTC, Etc/UCT, GMT0, Europe/Dublin, Etc/Zulu, Africa/Nouakchott, Europe/Isle_of_Man, Antarctica/Troll, Etc/GMT+0, Africa/Banjul, America/Danmarkshavn]
Instant: 2021-03-23T16:30:00Z in: [America/Scoresbysund, Atlantic/Cape_Verde, Atlantic/Azores, Etc/GMT+1]
Instant: 2021-03-23T17:30:00Z in: [Atlantic/South_Georgia, Brazil/DeNoronha, Etc/GMT+2, America/Miquelon, America/Noronha]
Instant: 2021-03-23T18:00:00Z in: [America/St_Johns, Canada/Newfoundland]
Instant: 2021-03-23T18:30:00Z in: [America/Argentina/San_Juan, America/Cordoba, America/Sao_Paulo, America/Thule, America/Argentina/Ushuaia, America/Mendoza, America/Moncton, America/Santarem, Canada/Atlantic, America/Asuncion, America/Belem, America/Montevideo, America/Argentina/ComodRivadavia, Atlantic/Bermuda, America/Jujuy, America/Fortaleza, America/Argentina/La_Rioja, Brazil/East, America/Recife, America/Buenos_Aires, Antarctica/Palmer, America/Bahia, America/Goose_Bay, America/Argentina/Jujuy, America/Maceio, America/Argentina/Tucuman, America/Argentina/Cordoba, America/Paramaribo, America/Argentina/Mendoza, America/Nuuk, America/Punta_Arenas, America/Araguaina, America/Argentina/Rio_Gallegos, America/Cayenne, Chile/Continental, America/Halifax, America/Argentina/Buenos_Aires, Antarctica/Rothera, America/Catamarca, America/Godthab, America/Argentina/Salta, Etc/GMT+3, America/Argentina/San_Luis, America/Rosario, Atlantic/Stanley, America/Argentina/Catamarca, America/Santiago, America/Glace_Bay]
Instant: 2021-03-23T19:30:00Z in: [America/Indianapolis, America/Cuiaba, America/Iqaluit, America/Curacao, America/Marigot, America/Blanc-Sablon, America/Indiana/Winamac, America/Guyana, America/Martinique, America/Kentucky/Monticello, Brazil/West, America/Boa_Vista, America/Aruba, America/St_Vincent, America/Grenada, America/Puerto_Rico, America/Tortola, America/Porto_Velho, America/Kentucky/Louisville, America/Manaus, America/Port_of_Spain, America/New_York, America/Indiana/Petersburg, America/Indiana/Indianapolis, America/Santo_Domingo, US/Eastern, America/St_Kitts, SystemV/AST4, America/Caracas, America/Dominica, America/Guadeloupe, Canada/Eastern, America/Port-au-Prince, America/St_Barthelemy, America/La_Paz, America/Nipigon, America/Indiana/Vevay, America/Campo_Grande, America/Fort_Wayne, EST5EDT, America/St_Thomas, America/Anguilla, US/East-Indiana, America/Virgin, America/Thunder_Bay, America/Grand_Turk, SystemV/AST4ADT, America/St_Lucia, America/Pangnirtung, America/Montserrat, America/Havana, America/Toronto, America/Indiana/Marengo, US/Michigan, America/Barbados, Cuba, America/Indiana/Vincennes, America/Nassau, America/Kralendijk, America/Antigua, America/Louisville, America/Lower_Princes, America/Montreal, America/Detroit, Etc/GMT+4]
Instant: 2021-03-23T20:30:00Z in: [America/Matamoros, America/Guayaquil, Brazil/Acre, America/North_Dakota/New_Salem, America/Coral_Harbour, America/North_Dakota/Center, America/Winnipeg, America/Indiana/Knox, America/Rankin_Inlet, America/Cancun, America/Cayman, America/Panama, America/North_Dakota/Beulah, CST6CDT, Pacific/Easter, America/Knox_IN, America/Lima, America/Bogota, America/Indiana/Tell_City, America/Menominee, America/Resolute, America/Porto_Acre, US/Central, US/Indiana-Starke, SystemV/EST5, SystemV/EST5EDT, America/Chicago, Chile/EasterIsland, America/Jamaica, Canada/Central, America/Eirunepe, America/Atikokan, America/Rainy_River, America/Rio_Branco, Jamaica, Etc/GMT+5]
Instant: 2021-03-23T21:30:00Z in: [America/Inuvik, America/Yellowknife, America/Regina, America/Boise, America/El_Salvador, America/Costa_Rica, America/Shiprock, America/Denver, America/Guatemala, America/Belize, SystemV/CST6CDT, Mexico/General, America/Swift_Current, America/Bahia_Banderas, America/Managua, Canada/Mountain, America/Cambridge_Bay, Navajo, America/Ojinaga, MST7MDT, America/Monterrey, America/Merida, Pacific/Galapagos, America/Mexico_City, America/Edmonton, US/Mountain, America/Tegucigalpa, Canada/Saskatchewan, Etc/GMT+6, SystemV/CST6]
Instant: 2021-03-23T22:30:00Z in: [America/Tijuana, America/Santa_Isabel, US/Arizona, Canada/Pacific, Canada/Yukon, Mexico/BajaSur, America/Chihuahua, SystemV/MST7MDT, America/Creston, America/Phoenix, America/Dawson_Creek, America/Los_Angeles, America/Whitehorse, America/Ensenada, America/Dawson, America/Mazatlan, PST8PDT, America/Hermosillo, America/Vancouver, SystemV/MST7, Etc/GMT+7, America/Fort_Nelson, US/Pacific, Mexico/BajaNorte]
Instant: 2021-03-23T23:30:00Z in: [America/Anchorage, America/Yakutat, America/Sitka, Etc/GMT+8, America/Metlakatla, Pacific/Pitcairn, SystemV/PST8, SystemV/PST8PDT, America/Juneau, America/Nome, US/Alaska]
Instant: 2021-03-24T00:30:00Z in: [Etc/GMT+9, America/Adak, US/Aleutian, America/Atka, SystemV/YST9, SystemV/YST9YDT, Pacific/Gambier]
Instant: 2021-03-24T01:00:00Z in: [Pacific/Marquesas]
Instant: 2021-03-24T01:30:00Z in: [Etc/GMT+10, Pacific/Honolulu, Pacific/Rarotonga, Pacific/Tahiti, US/Hawaii, Pacific/Johnston, SystemV/HST10]
Instant: 2021-03-24T02:30:00Z in: [Pacific/Pago_Pago, Pacific/Midway, Pacific/Niue, Pacific/Samoa, Etc/GMT+11, US/Samoa]
Instant: 2021-03-24T03:30:00Z in: [Etc/GMT+12]
您要求:
returns all Instants which are in the given time zone
每个时区每个 LocalDateTime
只有一个 Instant
。带时间的日期在一个时区内只能存在一次。
对于给定的一对 LocalDateTime
和 ZoneId
,列表中的所有时刻都将具有相同的值,因此创建这样的列表是没有用的。我相信您想要的是 ZonedDateTime
的列表,该列表对于该对具有相同的值,您可以按如下方式获得:
// ZonedDateTime for the given pair of LocalDateTime and ZoneId
ZonedDateTime zdt = dt.atZone(zone);
ZoneOffset offset = zdt.getOffset();
return ZoneId
.getAvailableZoneIds() // List of timezone names
.stream()
.map(tz -> dt.atZone(ZoneId.of(tz))) // Map the timezone to ZonedDateTime for dt
.filter(zt -> zt.getOffset().equals(offset)) // Keep only those ZonedDateTimes whose offset is equal to that of zdt
.collect(Collectors.toList());
演示:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
// Test
ZoneId zoneId = ZoneId.of("America/New_York");
LocalDateTime dt = LocalDateTime.now(zoneId);
localToZonedDateTimes(dt, zoneId).forEach(System.out::println);
}
static List<ZonedDateTime> localToZonedDateTimes(LocalDateTime dt, ZoneId zone) {
// ZonedDateTime for the given pair of LocalDateTime and ZoneId
ZonedDateTime zdt = dt.atZone(zone);
ZoneOffset offset = zdt.getOffset();
return ZoneId
.getAvailableZoneIds() // List of timezone names
.stream()
.map(tz -> dt.atZone(ZoneId.of(tz))) // Map the timezone to ZonedDateTime for dt
.filter(zt -> zt.getOffset().equals(offset)) // Keep only those ZonedDateTimes whose offset is equal to that of zdt
.collect(Collectors.toList());
}
}
输出:
2021-03-12T16:48:42.368606-05:00[America/Panama]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Petersburg]
2021-03-12T16:48:42.368606-05:00[America/Eirunepe]
2021-03-12T16:48:42.368606-05:00[America/Grand_Turk]
2021-03-12T16:48:42.368606-05:00[Cuba]
2021-03-12T16:48:42.368606-05:00[Etc/GMT+5]
2021-03-12T16:48:42.368606-05:00[Pacific/Easter]
2021-03-12T16:48:42.368606-05:00[America/Fort_Wayne]
2021-03-12T16:48:42.368606-05:00[America/Havana]
2021-03-12T16:48:42.368606-05:00[America/Porto_Acre]
2021-03-12T16:48:42.368606-05:00[US/Michigan]
2021-03-12T16:48:42.368606-05:00[America/Louisville]
2021-03-12T16:48:42.368606-05:00[America/Guayaquil]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Vevay]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Vincennes]
2021-03-12T16:48:42.368606-05:00[America/Indianapolis]
2021-03-12T16:48:42.368606-05:00[America/Iqaluit]
2021-03-12T16:48:42.368606-05:00[America/Kentucky/Louisville]
2021-03-12T16:48:42.368606-05:00[EST5EDT]
2021-03-12T16:48:42.368606-05:00[America/Nassau]
2021-03-12T16:48:42.368606-05:00[America/Jamaica]
2021-03-12T16:48:42.368606-05:00[America/Atikokan]
2021-03-12T16:48:42.368606-05:00[America/Kentucky/Monticello]
2021-03-12T16:48:42.368606-05:00[America/Coral_Harbour]
2021-03-12T16:48:42.368606-05:00[America/Cayman]
2021-03-12T16:48:42.368606-05:00[Chile/EasterIsland]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Indianapolis]
2021-03-12T16:48:42.368606-05:00[America/Thunder_Bay]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Marengo]
2021-03-12T16:48:42.368606-05:00[America/Bogota]
2021-03-12T16:48:42.368606-05:00[SystemV/EST5]
2021-03-12T16:48:42.368606-05:00[US/Eastern]
2021-03-12T16:48:42.368606-05:00[Canada/Eastern]
2021-03-12T16:48:42.368606-05:00[America/Port-au-Prince]
2021-03-12T16:48:42.368606-05:00[America/Nipigon]
2021-03-12T16:48:42.368606-05:00[Brazil/Acre]
2021-03-12T16:48:42.368606-05:00[US/East-Indiana]
2021-03-12T16:48:42.368606-05:00[America/Cancun]
2021-03-12T16:48:42.368606-05:00[America/Lima]
2021-03-12T16:48:42.368606-05:00[America/Rio_Branco]
2021-03-12T16:48:42.368606-05:00[America/Detroit]
2021-03-12T16:48:42.368606-05:00[Jamaica]
2021-03-12T16:48:42.368606-05:00[America/Pangnirtung]
2021-03-12T16:48:42.368606-05:00[America/Montreal]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Winamac]
2021-03-12T16:48:42.368606-05:00[America/New_York]
2021-03-12T16:48:42.368606-05:00[America/Toronto]
2021-03-12T16:48:42.368606-05:00[SystemV/EST5EDT]
了解有关现代日期时间的更多信息 API
是的✔️
编辑
米。 Prokhorov 使用 ZoneRules.getValidOffset()
的想法给出了比我原来的答案更优雅的代码。这是一个根据要求 returns 列表 Instant
s 的版本:
public static List<Instant> localToInstants(LocalDateTime dt, ZoneId zone) {
return zone.getRules()
.getValidOffsets(dt)
.stream()
.map(dt::atOffset)
.map(OffsetDateTime::toInstant)
.collect(Collectors.toList());
}
让我们在几个重要的例子上试试看。马耳他将于 3 月 28 日过渡到夏令时。凌晨 2 点,时钟拨快至 3 点。因此,时间 2:30 在这一天不存在。这意味着我们期望从以下调用中得到一个空列表:
LocalDateTime dt = LocalDateTime.of(2021, Month.MARCH, 28, 2, 30);
System.out.println(localToInstants(dt, ZoneId.of("Europe/Malta")));
输出确实是:
[]
这是Java打印空列表的方式。工作原理:由于时间不存在,ZoneRules.getValidOffsets()
return 是一个空列表。其余的很无聊:没有偏移量可以转换为 OffsetDateTime
并进一步转换为 Instant
,因此空列表是 returned.
我的另一个例子来自 Eater Island。根据我的 Java 9 夏令时将在 5 月 8 日结束。在 22 时时钟将拨回到 21。所以时间 21:30 出现了两次。让我们看看:
LocalDateTime dt = LocalDateTime.of(2021, Month.MAY, 8, 21, 30);
System.out.println(localToInstants(dt, ZoneId.of("Pacific/Easter")));
[2021-05-09T02:30:00Z, 2021-05-09T03:30:00Z]
由于 UTC 偏移量从 -05:00 变为 -06:00,所以时刻是正确的。在这种情况下,getValidOffsets()
return 编辑了两个有效偏移量,-05:00 和 -06:00,因此代码生成了两个 OffsetDateTime
对象,这些对象又被转换为两个不同的 Instant
对象。
原回答
如果有人有兴趣获得合适的 ZonedDateTime
对象,我将保留此立场。
public static List<Instant> localToInstants(LocalDateTime dt, ZoneId zone) {
return Stream.of(dt.atZone(zone).withEarlierOffsetAtOverlap(),
dt.atZone(zone).withLaterOffsetAtOverlap())
.filter(zdt -> zdt.toLocalDateTime().equals(dt))
.map(ZonedDateTime::toInstant)
.distinct()
.collect(Collectors.toList());
}
让我们在几个重要的例子上试试看。马耳他将于 3 月 28 日过渡到夏令时。凌晨 2 点,时钟拨快至 3 点。因此,时间 2:30 在这一天不存在。这意味着我们期望从以下调用中得到一个空列表:
LocalDateTime dt = LocalDateTime.of(2021, Month.MARCH, 28, 2, 30);
System.out.println(localToInstants(dt, ZoneId.of("Europe/Malta")));
输出确实是:
[]
这是Java打印空列表的方式。工作原理:由于时间不存在,dt.atZone(zone)
给我们 3:30 而不是 2:30。 Java 添加间隔的长度,夏令时过渡通常为一小时。在这种情况下,对 withEarlierOffsetAtOverlap()
和 withLaterOffsetAtOverlap()
的调用没有任何区别(我将对它们 return ),所以我们只得到相同的 ZonedDateTime
两次。对 filter()
的调用造成了差异:我们将 ZonedDateTime
转换回 LocalDateTime
并发现我们没有得到相同的时间,因此我们丢弃了结果。剩下的很无聊:没有 ZonedDateTime
可以转换为 Instant
,所以我们最终得到一个空列表。
我的另一个例子来自 Eater Island。根据我的 Java 9 夏令时将在 5 月 8 日结束。在 22 时时钟将拨回到 21。所以时间 21:30 出现了两次。让我们看看:
LocalDateTime dt = LocalDateTime.of(2021, Month.MAY, 8, 21, 30);
System.out.println(localToInstants(dt, ZoneId.of("Pacific/Easter")));
[2021-05-09T02:30:00Z, 2021-05-09T03:30:00Z]
由于 UTC 偏移量从 -05:00 变为 -06:00,所以时刻是正确的。它是如何工作的:这里是对 withEarlierOffsetAtOverlap()
和 withLaterOffsetAtOverlap()
的调用发挥作用的地方。 dt.atZone(zone)
给了我们一个选项(2021-05-08T21:30-05:00[Pacific/Easter]
,所以较早的一个,但没有一个理智的人会记住它)。因为 Java 知道此时有重叠,所以 withEarlierOffsetAtOverlap()
和 withLaterOffsetAtOverlap()
给了我们两种不同的可能性。由于两者都转换回正确的 LocalDateTime
,因此不会过滤掉任何内容。由于两者是不同的时刻,distinct()
也不会过滤掉任何东西。我们最终得到两个 Instant
个对象。
文档 link
在将Instant
转换为LocalDateTime
时,可能会出现几个不同的Instant
转换为相同的LocalDateTime
的情况。例如。在有夏令时的时区。
我的问题是是否可以编写一个适用于任何 ZoneId
和 LocalDateTime
以及 returns 所有 Instant
在给定时间内的通用函数映射到给定 LocalDateTime
:
List<Instant> localToInstants(LocalDateTime dt, ZoneId zone)
对于任何给定的一对 LocalDateTime
和 ZoneId
,只有一个 Instant
- 因为 Instant
是 UTC 偏移量的时刻,+0:0 .
您可能正在寻找从 LocalDateTime
到 List<OffsetDateTime>
的转换,其编码如下:
List<OffsetDateTime> localToOffsets(LocalDateTime ldt, ZoneId zone) {
ZoneRules rules = zone.getRules();
return rules.getValidOffsets(ldt).stream()
.map(ldt::atOffset)
.collect(Collectors.toList());
}
循环所有时区,将每个时区指定为您的 LocalDateTime
. From each ZonedDateTime
object produced you can extract an Instant
的上下文。其中一些 Instant
对象将代表同一时刻,其中各个时区碰巧在该日期和时间共享相同的距 UTC 的偏移量。
在此示例代码中,我们从特定的 LocalDateTime
开始。这意味着日期带有一天中的时间——在没有时区或与 UTC 的偏移量的情况下本质上是模棱两可的。我们将 LocalDateTime
重复放置在这样的上下文中,放置在 ZonedDateTime
对象的 tzdata within our version of Java. The result of placing LocalDateTime
in a ZoneId
is a ZonedDateTime
. We then extract an Instant
, effectively adjusting to UTC as Instant
is a moment as seen in UTC. We put the Instant
object into a Map
as the key. For the value of the map, we have a collection of ZonedDateTime
objects that report that same instant. So we have a multimap, a map of key Instant
to multiple values, a Set
已知的每个时区中。
LocalDateTime myLocalDateTime = LocalDateTime.of( 2021 , Month.MARCH , 23 , 15 , 30 , 0 , 0 );
Set < String > zoneNames = ZoneId.getAvailableZoneIds();
NavigableMap < Instant, NavigableSet < ZonedDateTime > > instantToZdts = new TreeMap <>();
for ( String zoneName : zoneNames )
{
ZoneId z = ZoneId.of( zoneName );
ZonedDateTime zdt = myLocalDateTime.atZone( z );
Instant instant = zdt.toInstant();
//System.out.println( myLocalDateTime + " in " + z + " is " + zdt + " = " + instant );
instantToZdts.putIfAbsent( instant , new TreeSet <>() );
instantToZdts.get( instant ).add( zdt );
}
向控制台报告结果。
System.out.println( "instantToZdts = " + instantToZdts );
System.out.println( "---------------| " + myLocalDateTime + " |-----------------------" );
System.out.println( "" ) ;
for ( Instant instant : instantToZdts.keySet() )
{
Set < ZoneId > zoneIds = instantToZdts.get( instant ).stream().map( zonedDateTime -> zonedDateTime.getZone() ).collect( Collectors.toSet() );
System.out.println( "Instant: " + instant + " in: " + zoneIds );
System.out.println( "" );
}
当运行.
---------------| 2021-03-23T15:30 |-----------------------
Instant: 2021-03-23T01:30:00Z in: [Pacific/Apia, Pacific/Kiritimati, Etc/GMT-14]
Instant: 2021-03-23T01:45:00Z in: [Pacific/Chatham, NZ-CHAT]
Instant: 2021-03-23T02:30:00Z in: [Antarctica/McMurdo, Pacific/Tongatapu, Pacific/Enderbury, Pacific/Fakaofo, NZ, Antarctica/South_Pole, Pacific/Auckland, Etc/GMT-13]
Instant: 2021-03-23T03:30:00Z in: [Pacific/Funafuti, Pacific/Norfolk, Etc/GMT-12, Asia/Kamchatka, Pacific/Tarawa, Kwajalein, Pacific/Kwajalein, Asia/Anadyr, Pacific/Majuro, Pacific/Wake, Pacific/Nauru, Pacific/Fiji, Pacific/Wallis]
Instant: 2021-03-23T04:30:00Z in: [Australia/Sydney, Australia/LHI, Pacific/Efate, Asia/Magadan, Antarctica/Casey, Antarctica/Macquarie, Australia/Lord_Howe, Australia/Victoria, Etc/GMT-11, Pacific/Bougainville, Asia/Srednekolymsk, Australia/Tasmania, Australia/Currie, Pacific/Pohnpei, Australia/Melbourne, Pacific/Noumea, Australia/Hobart, Pacific/Guadalcanal, Pacific/Ponape, Australia/ACT, Australia/Canberra, Australia/NSW, Pacific/Kosrae, Asia/Sakhalin]
Instant: 2021-03-23T05:00:00Z in: [Australia/Adelaide, Australia/South, Australia/Broken_Hill, Australia/Yancowinna]
Instant: 2021-03-23T05:30:00Z in: [Pacific/Port_Moresby, Asia/Vladivostok, Pacific/Saipan, Asia/Ust-Nera, Antarctica/DumontDUrville, Etc/GMT-10, Pacific/Truk, Australia/Lindeman, Pacific/Chuuk, Australia/Brisbane, Pacific/Guam, Pacific/Yap, Australia/Queensland]
Instant: 2021-03-23T06:00:00Z in: [Australia/North, Australia/Darwin]
Instant: 2021-03-23T06:30:00Z in: [Asia/Pyongyang, Asia/Tokyo, Asia/Yakutsk, Asia/Jayapura, Asia/Dili, Japan, Asia/Khandyga, Pacific/Palau, Asia/Chita, Etc/GMT-9, Asia/Seoul, ROK]
Instant: 2021-03-23T06:45:00Z in: [Australia/Eucla]
Instant: 2021-03-23T07:30:00Z in: [PRC, Singapore, Hongkong, Asia/Hong_Kong, Asia/Taipei, Asia/Ulan_Bator, Asia/Manila, Asia/Irkutsk, Asia/Ujung_Pandang, Asia/Harbin, Asia/Kuching, Asia/Chongqing, Australia/Perth, Asia/Kuala_Lumpur, Asia/Ulaanbaatar, Asia/Chungking, Asia/Macao, Asia/Shanghai, Asia/Brunei, Asia/Macau, Asia/Choibalsan, Australia/West, Asia/Singapore, Asia/Makassar, Etc/GMT-8]
Instant: 2021-03-23T08:30:00Z in: [Asia/Vientiane, Asia/Ho_Chi_Minh, Asia/Tomsk, Asia/Phnom_Penh, Asia/Jakarta, Asia/Hovd, Asia/Barnaul, Asia/Krasnoyarsk, Asia/Pontianak, Asia/Bangkok, Asia/Saigon, Asia/Novokuznetsk, Asia/Novosibirsk, Indian/Christmas, Antarctica/Davis, Etc/GMT-7]
Instant: 2021-03-23T09:00:00Z in: [Asia/Yangon, Indian/Cocos, Asia/Rangoon]
Instant: 2021-03-23T09:30:00Z in: [Asia/Dacca, Asia/Thimbu, Asia/Omsk, Asia/Qostanay, Asia/Almaty, Asia/Dhaka, Indian/Chagos, Asia/Kashgar, Asia/Urumqi, Antarctica/Vostok, Asia/Bishkek, Asia/Thimphu, Etc/GMT-6]
Instant: 2021-03-23T09:45:00Z in: [Asia/Katmandu, Asia/Kathmandu]
Instant: 2021-03-23T10:00:00Z in: [Asia/Calcutta, Asia/Colombo, Asia/Kolkata]
Instant: 2021-03-23T10:30:00Z in: [Asia/Aqtobe, Asia/Samarkand, Indian/Kerguelen, Asia/Oral, Asia/Ashgabat, Asia/Dushanbe, Asia/Aqtau, Asia/Ashkhabad, Asia/Tashkent, Antarctica/Mawson, Asia/Karachi, Asia/Atyrau, Asia/Yekaterinburg, Etc/GMT-5, Asia/Qyzylorda, Indian/Maldives]
Instant: 2021-03-23T11:00:00Z in: [Asia/Kabul, Asia/Tehran, Iran]
Instant: 2021-03-23T11:30:00Z in: [Indian/Mahe, Indian/Mauritius, Europe/Astrakhan, Indian/Reunion, Asia/Yerevan, Europe/Ulyanovsk, Asia/Dubai, Asia/Muscat, Asia/Tbilisi, Europe/Samara, Europe/Saratov, Europe/Volgograd, Etc/GMT-4, Asia/Baku]
Instant: 2021-03-23T12:30:00Z in: [Asia/Aden, Asia/Qatar, Africa/Nairobi, Antarctica/Syowa, Africa/Juba, Asia/Riyadh, Europe/Moscow, Asia/Bahrain, Africa/Mogadishu, Africa/Dar_es_Salaam, Asia/Baghdad, Asia/Kuwait, Africa/Addis_Ababa, Asia/Istanbul, Africa/Djibouti, Europe/Kirov, Africa/Asmara, Africa/Asmera, Europe/Simferopol, Indian/Antananarivo, Africa/Kampala, Indian/Mayotte, W-SU, Turkey, Europe/Istanbul, Etc/GMT-3, Indian/Comoro, Europe/Minsk]
Instant: 2021-03-23T13:30:00Z in: [Europe/Kiev, Asia/Hebron, Egypt, Europe/Zaporozhye, Asia/Nicosia, Africa/Lusaka, Africa/Gaborone, Africa/Maputo, Europe/Kaliningrad, Libya, Africa/Cairo, Africa/Windhoek, Europe/Mariehamn, Africa/Mbabane, Europe/Vilnius, Asia/Gaza, Europe/Chisinau, Asia/Famagusta, Africa/Maseru, Asia/Amman, Africa/Lubumbashi, Europe/Bucharest, Europe/Uzhgorod, Europe/Helsinki, Asia/Beirut, Africa/Harare, Asia/Tel_Aviv, Africa/Kigali, Europe/Sofia, Europe/Tallinn, Africa/Khartoum, EET, Europe/Tiraspol, Africa/Johannesburg, Europe/Nicosia, Asia/Damascus, Africa/Bujumbura, Asia/Jerusalem, Europe/Athens, Africa/Tripoli, Etc/GMT-2, Israel, Africa/Blantyre, Europe/Riga]
Instant: 2021-03-23T14:30:00Z in: [Europe/Ljubljana, Africa/Libreville, Europe/Berlin, Africa/El_Aaiun, Europe/Oslo, Europe/Stockholm, Europe/Budapest, Europe/Bratislava, Europe/San_Marino, Europe/Zagreb, Europe/Copenhagen, Europe/Malta, Europe/Brussels, Europe/Vienna, Africa/Douala, Europe/Busingen, Europe/Warsaw, CET, Africa/Malabo, Etc/GMT-1, Europe/Podgorica, Europe/Skopje, Europe/Paris, Africa/Ndjamena, Europe/Sarajevo, Europe/Tirane, Africa/Bangui, Europe/Luxembourg, Europe/Belgrade, Arctic/Longyearbyen, MET, Africa/Casablanca, Africa/Lagos, Europe/Rome, Africa/Brazzaville, Africa/Luanda, Africa/Porto-Novo, Atlantic/Jan_Mayen, Africa/Ceuta, Africa/Algiers, Europe/Zurich, Europe/Amsterdam, Poland, Europe/Vatican, Europe/Gibraltar, Africa/Kinshasa, Europe/Madrid, Europe/Vaduz, Africa/Niamey, Europe/Prague, Africa/Tunis, Europe/Andorra, Europe/Monaco]
Instant: 2021-03-23T15:30:00Z in: [UTC, UCT, Portugal, Iceland, Zulu, Africa/Ouagadougou, Europe/Lisbon, Etc/Universal, Europe/London, Atlantic/Faeroe, Africa/Dakar, Etc/GMT, Atlantic/Canary, Africa/Lome, Universal, Africa/Freetown, Africa/Sao_Tome, GMT, Greenwich, Etc/GMT-0, Europe/Jersey, GB-Eire, Africa/Bissau, Europe/Belfast, Africa/Abidjan, Atlantic/Reykjavik, Africa/Monrovia, WET, Atlantic/St_Helena, Etc/Greenwich, Etc/GMT0, Africa/Bamako, Eire, Europe/Guernsey, Africa/Timbuktu, Atlantic/Madeira, GB, Africa/Accra, Africa/Conakry, Atlantic/Faroe, Etc/UTC, Etc/UCT, GMT0, Europe/Dublin, Etc/Zulu, Africa/Nouakchott, Europe/Isle_of_Man, Antarctica/Troll, Etc/GMT+0, Africa/Banjul, America/Danmarkshavn]
Instant: 2021-03-23T16:30:00Z in: [America/Scoresbysund, Atlantic/Cape_Verde, Atlantic/Azores, Etc/GMT+1]
Instant: 2021-03-23T17:30:00Z in: [Atlantic/South_Georgia, Brazil/DeNoronha, Etc/GMT+2, America/Miquelon, America/Noronha]
Instant: 2021-03-23T18:00:00Z in: [America/St_Johns, Canada/Newfoundland]
Instant: 2021-03-23T18:30:00Z in: [America/Argentina/San_Juan, America/Cordoba, America/Sao_Paulo, America/Thule, America/Argentina/Ushuaia, America/Mendoza, America/Moncton, America/Santarem, Canada/Atlantic, America/Asuncion, America/Belem, America/Montevideo, America/Argentina/ComodRivadavia, Atlantic/Bermuda, America/Jujuy, America/Fortaleza, America/Argentina/La_Rioja, Brazil/East, America/Recife, America/Buenos_Aires, Antarctica/Palmer, America/Bahia, America/Goose_Bay, America/Argentina/Jujuy, America/Maceio, America/Argentina/Tucuman, America/Argentina/Cordoba, America/Paramaribo, America/Argentina/Mendoza, America/Nuuk, America/Punta_Arenas, America/Araguaina, America/Argentina/Rio_Gallegos, America/Cayenne, Chile/Continental, America/Halifax, America/Argentina/Buenos_Aires, Antarctica/Rothera, America/Catamarca, America/Godthab, America/Argentina/Salta, Etc/GMT+3, America/Argentina/San_Luis, America/Rosario, Atlantic/Stanley, America/Argentina/Catamarca, America/Santiago, America/Glace_Bay]
Instant: 2021-03-23T19:30:00Z in: [America/Indianapolis, America/Cuiaba, America/Iqaluit, America/Curacao, America/Marigot, America/Blanc-Sablon, America/Indiana/Winamac, America/Guyana, America/Martinique, America/Kentucky/Monticello, Brazil/West, America/Boa_Vista, America/Aruba, America/St_Vincent, America/Grenada, America/Puerto_Rico, America/Tortola, America/Porto_Velho, America/Kentucky/Louisville, America/Manaus, America/Port_of_Spain, America/New_York, America/Indiana/Petersburg, America/Indiana/Indianapolis, America/Santo_Domingo, US/Eastern, America/St_Kitts, SystemV/AST4, America/Caracas, America/Dominica, America/Guadeloupe, Canada/Eastern, America/Port-au-Prince, America/St_Barthelemy, America/La_Paz, America/Nipigon, America/Indiana/Vevay, America/Campo_Grande, America/Fort_Wayne, EST5EDT, America/St_Thomas, America/Anguilla, US/East-Indiana, America/Virgin, America/Thunder_Bay, America/Grand_Turk, SystemV/AST4ADT, America/St_Lucia, America/Pangnirtung, America/Montserrat, America/Havana, America/Toronto, America/Indiana/Marengo, US/Michigan, America/Barbados, Cuba, America/Indiana/Vincennes, America/Nassau, America/Kralendijk, America/Antigua, America/Louisville, America/Lower_Princes, America/Montreal, America/Detroit, Etc/GMT+4]
Instant: 2021-03-23T20:30:00Z in: [America/Matamoros, America/Guayaquil, Brazil/Acre, America/North_Dakota/New_Salem, America/Coral_Harbour, America/North_Dakota/Center, America/Winnipeg, America/Indiana/Knox, America/Rankin_Inlet, America/Cancun, America/Cayman, America/Panama, America/North_Dakota/Beulah, CST6CDT, Pacific/Easter, America/Knox_IN, America/Lima, America/Bogota, America/Indiana/Tell_City, America/Menominee, America/Resolute, America/Porto_Acre, US/Central, US/Indiana-Starke, SystemV/EST5, SystemV/EST5EDT, America/Chicago, Chile/EasterIsland, America/Jamaica, Canada/Central, America/Eirunepe, America/Atikokan, America/Rainy_River, America/Rio_Branco, Jamaica, Etc/GMT+5]
Instant: 2021-03-23T21:30:00Z in: [America/Inuvik, America/Yellowknife, America/Regina, America/Boise, America/El_Salvador, America/Costa_Rica, America/Shiprock, America/Denver, America/Guatemala, America/Belize, SystemV/CST6CDT, Mexico/General, America/Swift_Current, America/Bahia_Banderas, America/Managua, Canada/Mountain, America/Cambridge_Bay, Navajo, America/Ojinaga, MST7MDT, America/Monterrey, America/Merida, Pacific/Galapagos, America/Mexico_City, America/Edmonton, US/Mountain, America/Tegucigalpa, Canada/Saskatchewan, Etc/GMT+6, SystemV/CST6]
Instant: 2021-03-23T22:30:00Z in: [America/Tijuana, America/Santa_Isabel, US/Arizona, Canada/Pacific, Canada/Yukon, Mexico/BajaSur, America/Chihuahua, SystemV/MST7MDT, America/Creston, America/Phoenix, America/Dawson_Creek, America/Los_Angeles, America/Whitehorse, America/Ensenada, America/Dawson, America/Mazatlan, PST8PDT, America/Hermosillo, America/Vancouver, SystemV/MST7, Etc/GMT+7, America/Fort_Nelson, US/Pacific, Mexico/BajaNorte]
Instant: 2021-03-23T23:30:00Z in: [America/Anchorage, America/Yakutat, America/Sitka, Etc/GMT+8, America/Metlakatla, Pacific/Pitcairn, SystemV/PST8, SystemV/PST8PDT, America/Juneau, America/Nome, US/Alaska]
Instant: 2021-03-24T00:30:00Z in: [Etc/GMT+9, America/Adak, US/Aleutian, America/Atka, SystemV/YST9, SystemV/YST9YDT, Pacific/Gambier]
Instant: 2021-03-24T01:00:00Z in: [Pacific/Marquesas]
Instant: 2021-03-24T01:30:00Z in: [Etc/GMT+10, Pacific/Honolulu, Pacific/Rarotonga, Pacific/Tahiti, US/Hawaii, Pacific/Johnston, SystemV/HST10]
Instant: 2021-03-24T02:30:00Z in: [Pacific/Pago_Pago, Pacific/Midway, Pacific/Niue, Pacific/Samoa, Etc/GMT+11, US/Samoa]
Instant: 2021-03-24T03:30:00Z in: [Etc/GMT+12]
您要求:
returns all Instants which are in the given time zone
每个时区每个 LocalDateTime
只有一个 Instant
。带时间的日期在一个时区内只能存在一次。
对于给定的一对 LocalDateTime
和 ZoneId
,列表中的所有时刻都将具有相同的值,因此创建这样的列表是没有用的。我相信您想要的是 ZonedDateTime
的列表,该列表对于该对具有相同的值,您可以按如下方式获得:
// ZonedDateTime for the given pair of LocalDateTime and ZoneId
ZonedDateTime zdt = dt.atZone(zone);
ZoneOffset offset = zdt.getOffset();
return ZoneId
.getAvailableZoneIds() // List of timezone names
.stream()
.map(tz -> dt.atZone(ZoneId.of(tz))) // Map the timezone to ZonedDateTime for dt
.filter(zt -> zt.getOffset().equals(offset)) // Keep only those ZonedDateTimes whose offset is equal to that of zdt
.collect(Collectors.toList());
演示:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
// Test
ZoneId zoneId = ZoneId.of("America/New_York");
LocalDateTime dt = LocalDateTime.now(zoneId);
localToZonedDateTimes(dt, zoneId).forEach(System.out::println);
}
static List<ZonedDateTime> localToZonedDateTimes(LocalDateTime dt, ZoneId zone) {
// ZonedDateTime for the given pair of LocalDateTime and ZoneId
ZonedDateTime zdt = dt.atZone(zone);
ZoneOffset offset = zdt.getOffset();
return ZoneId
.getAvailableZoneIds() // List of timezone names
.stream()
.map(tz -> dt.atZone(ZoneId.of(tz))) // Map the timezone to ZonedDateTime for dt
.filter(zt -> zt.getOffset().equals(offset)) // Keep only those ZonedDateTimes whose offset is equal to that of zdt
.collect(Collectors.toList());
}
}
输出:
2021-03-12T16:48:42.368606-05:00[America/Panama]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Petersburg]
2021-03-12T16:48:42.368606-05:00[America/Eirunepe]
2021-03-12T16:48:42.368606-05:00[America/Grand_Turk]
2021-03-12T16:48:42.368606-05:00[Cuba]
2021-03-12T16:48:42.368606-05:00[Etc/GMT+5]
2021-03-12T16:48:42.368606-05:00[Pacific/Easter]
2021-03-12T16:48:42.368606-05:00[America/Fort_Wayne]
2021-03-12T16:48:42.368606-05:00[America/Havana]
2021-03-12T16:48:42.368606-05:00[America/Porto_Acre]
2021-03-12T16:48:42.368606-05:00[US/Michigan]
2021-03-12T16:48:42.368606-05:00[America/Louisville]
2021-03-12T16:48:42.368606-05:00[America/Guayaquil]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Vevay]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Vincennes]
2021-03-12T16:48:42.368606-05:00[America/Indianapolis]
2021-03-12T16:48:42.368606-05:00[America/Iqaluit]
2021-03-12T16:48:42.368606-05:00[America/Kentucky/Louisville]
2021-03-12T16:48:42.368606-05:00[EST5EDT]
2021-03-12T16:48:42.368606-05:00[America/Nassau]
2021-03-12T16:48:42.368606-05:00[America/Jamaica]
2021-03-12T16:48:42.368606-05:00[America/Atikokan]
2021-03-12T16:48:42.368606-05:00[America/Kentucky/Monticello]
2021-03-12T16:48:42.368606-05:00[America/Coral_Harbour]
2021-03-12T16:48:42.368606-05:00[America/Cayman]
2021-03-12T16:48:42.368606-05:00[Chile/EasterIsland]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Indianapolis]
2021-03-12T16:48:42.368606-05:00[America/Thunder_Bay]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Marengo]
2021-03-12T16:48:42.368606-05:00[America/Bogota]
2021-03-12T16:48:42.368606-05:00[SystemV/EST5]
2021-03-12T16:48:42.368606-05:00[US/Eastern]
2021-03-12T16:48:42.368606-05:00[Canada/Eastern]
2021-03-12T16:48:42.368606-05:00[America/Port-au-Prince]
2021-03-12T16:48:42.368606-05:00[America/Nipigon]
2021-03-12T16:48:42.368606-05:00[Brazil/Acre]
2021-03-12T16:48:42.368606-05:00[US/East-Indiana]
2021-03-12T16:48:42.368606-05:00[America/Cancun]
2021-03-12T16:48:42.368606-05:00[America/Lima]
2021-03-12T16:48:42.368606-05:00[America/Rio_Branco]
2021-03-12T16:48:42.368606-05:00[America/Detroit]
2021-03-12T16:48:42.368606-05:00[Jamaica]
2021-03-12T16:48:42.368606-05:00[America/Pangnirtung]
2021-03-12T16:48:42.368606-05:00[America/Montreal]
2021-03-12T16:48:42.368606-05:00[America/Indiana/Winamac]
2021-03-12T16:48:42.368606-05:00[America/New_York]
2021-03-12T16:48:42.368606-05:00[America/Toronto]
2021-03-12T16:48:42.368606-05:00[SystemV/EST5EDT]
了解有关现代日期时间的更多信息 API
是的✔️
编辑
米。 Prokhorov 使用 ZoneRules.getValidOffset()
的想法给出了比我原来的答案更优雅的代码。这是一个根据要求 returns 列表 Instant
s 的版本:
public static List<Instant> localToInstants(LocalDateTime dt, ZoneId zone) {
return zone.getRules()
.getValidOffsets(dt)
.stream()
.map(dt::atOffset)
.map(OffsetDateTime::toInstant)
.collect(Collectors.toList());
}
让我们在几个重要的例子上试试看。马耳他将于 3 月 28 日过渡到夏令时。凌晨 2 点,时钟拨快至 3 点。因此,时间 2:30 在这一天不存在。这意味着我们期望从以下调用中得到一个空列表:
LocalDateTime dt = LocalDateTime.of(2021, Month.MARCH, 28, 2, 30);
System.out.println(localToInstants(dt, ZoneId.of("Europe/Malta")));
输出确实是:
[]
这是Java打印空列表的方式。工作原理:由于时间不存在,ZoneRules.getValidOffsets()
return 是一个空列表。其余的很无聊:没有偏移量可以转换为 OffsetDateTime
并进一步转换为 Instant
,因此空列表是 returned.
我的另一个例子来自 Eater Island。根据我的 Java 9 夏令时将在 5 月 8 日结束。在 22 时时钟将拨回到 21。所以时间 21:30 出现了两次。让我们看看:
LocalDateTime dt = LocalDateTime.of(2021, Month.MAY, 8, 21, 30);
System.out.println(localToInstants(dt, ZoneId.of("Pacific/Easter")));
[2021-05-09T02:30:00Z, 2021-05-09T03:30:00Z]
由于 UTC 偏移量从 -05:00 变为 -06:00,所以时刻是正确的。在这种情况下,getValidOffsets()
return 编辑了两个有效偏移量,-05:00 和 -06:00,因此代码生成了两个 OffsetDateTime
对象,这些对象又被转换为两个不同的 Instant
对象。
原回答
如果有人有兴趣获得合适的 ZonedDateTime
对象,我将保留此立场。
public static List<Instant> localToInstants(LocalDateTime dt, ZoneId zone) {
return Stream.of(dt.atZone(zone).withEarlierOffsetAtOverlap(),
dt.atZone(zone).withLaterOffsetAtOverlap())
.filter(zdt -> zdt.toLocalDateTime().equals(dt))
.map(ZonedDateTime::toInstant)
.distinct()
.collect(Collectors.toList());
}
让我们在几个重要的例子上试试看。马耳他将于 3 月 28 日过渡到夏令时。凌晨 2 点,时钟拨快至 3 点。因此,时间 2:30 在这一天不存在。这意味着我们期望从以下调用中得到一个空列表:
LocalDateTime dt = LocalDateTime.of(2021, Month.MARCH, 28, 2, 30);
System.out.println(localToInstants(dt, ZoneId.of("Europe/Malta")));
输出确实是:
[]
这是Java打印空列表的方式。工作原理:由于时间不存在,dt.atZone(zone)
给我们 3:30 而不是 2:30。 Java 添加间隔的长度,夏令时过渡通常为一小时。在这种情况下,对 withEarlierOffsetAtOverlap()
和 withLaterOffsetAtOverlap()
的调用没有任何区别(我将对它们 return ),所以我们只得到相同的 ZonedDateTime
两次。对 filter()
的调用造成了差异:我们将 ZonedDateTime
转换回 LocalDateTime
并发现我们没有得到相同的时间,因此我们丢弃了结果。剩下的很无聊:没有 ZonedDateTime
可以转换为 Instant
,所以我们最终得到一个空列表。
我的另一个例子来自 Eater Island。根据我的 Java 9 夏令时将在 5 月 8 日结束。在 22 时时钟将拨回到 21。所以时间 21:30 出现了两次。让我们看看:
LocalDateTime dt = LocalDateTime.of(2021, Month.MAY, 8, 21, 30);
System.out.println(localToInstants(dt, ZoneId.of("Pacific/Easter")));
[2021-05-09T02:30:00Z, 2021-05-09T03:30:00Z]
由于 UTC 偏移量从 -05:00 变为 -06:00,所以时刻是正确的。它是如何工作的:这里是对 withEarlierOffsetAtOverlap()
和 withLaterOffsetAtOverlap()
的调用发挥作用的地方。 dt.atZone(zone)
给了我们一个选项(2021-05-08T21:30-05:00[Pacific/Easter]
,所以较早的一个,但没有一个理智的人会记住它)。因为 Java 知道此时有重叠,所以 withEarlierOffsetAtOverlap()
和 withLaterOffsetAtOverlap()
给了我们两种不同的可能性。由于两者都转换回正确的 LocalDateTime
,因此不会过滤掉任何内容。由于两者是不同的时刻,distinct()
也不会过滤掉任何东西。我们最终得到两个 Instant
个对象。