gpt4 book ai didi

java - 从Lambda表达式中获取时区(java)

转载 作者:行者123 更新时间:2023-12-02 13:22:53 28 4
gpt4 key购买 nike

因此,我试图在java gui中创建2个下拉菜单,使用户可以在时区之间进行选择并比较其中两个。但是我在尝试获取用户从lambda表达式中选择的时区变量时遇到问题。我对Java还是很陌生,所以请您提供任何帮助

这是给我问题的代码

 tz tz1= new tz();

ComboBox<String> cboNation = new ComboBox<>();
ObservableList<String> items = FXCollections.observableArrayList
("GMT+14", "GMT+13", "GMT+12", "GMT+11","GMT+10", "GMT+9", "GMT+8",
"GMT+7", "GMT+6", "GMT+5", "GMT+4", "GMT+3", "GMT+2", "GMT+1",
"GMT0" ,"GMT-1", "GMT-2", "GMT-3", "GMT-4", "GMT-5", "GMT-6",
"GMT-7", "GMT-8", "GMT-9", "GMT-10", "GMT-11", "GMT-12", "GMT-13", "GMT-14");
cboNation.getItems().addAll(items);
cboNation.setValue(items.get(0));
cboNation.setOnAction(e ->
{

currentIndex = items.indexOf(cboNation.getValue());
TimeZone tz = TimeZone.getTimeZone(timezones[currentIndex]);
String Timezone2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(tz);
tz1.firstdisplay = Timezone2;
});

gridPane.add(new Label(tz1.firstdisplay), 0, 0);


我希望能够从表达式中获取tz并将其格式化为显示日期的字符串。如果有帮助的话,它将在gui上显示。

编辑
我尝试通过引用传递程序,该程序现在可以运行,但时区未显示在gui中。我添加了应该向他们显示的行,但没有任何反应

最佳答案

tl; dr

定义ComboBox < ZoneOffset > offsetsMenu而不是<String>

offsetsMenu.setOnAction( ( ActionEvent actionEvent ) -> { this.chosenOffset = offsetsMenu.getValue(); } );



我实际上并没有解决您的问题,而是简化了代码以消除问题。
你太辛苦了


通过泛型,使用智能对象而不是哑字符串来支持菜单。
使弹出菜单小部件的类型为 ZoneOffset,以避免在后备列表中查找。

仅将现代java.time类用于日期时间工作。在此,具体使用 InstantZoneOffsetZoneIdZoneRules


切勿使用 TimeZoneSimpleDateFormatjava.util.Date等。



时区与偏移量

偏移量


  在时区之间进行选择,并比较其中两个。
  
  …
  
  (“ GMT + 14”,“ GMT + 13”,“ GMT + 12”,“ GMT + 11”,“ GMT + 10”,“ GMT + 9”,“ GMT + 8”,
     “ GMT + 7”,“ GMT + 6”,“ GMT + 5”,“ GMT + 4”,“ GMT + 3”,“ GMT + 2”,“ GMT + 1”,
     “ GMT0”,“ GMT-1”,“ GMT-2”,“ GMT-3”,“ GMT-4”,“ GMT-5”,“ GMT-6”,
     “ GMT-7”,“ GMT-8”,“ GMT-9”,“ GMT-10”,“ GMT-11”,“ GMT-12”,“ GMT-13”,“ GMT-14”);


这些不是时区。这些是偏移量,在本初子午线之前或之后数小时-数分钟-秒。

他们还不完整。偏移量可以是任何小时数-分钟-秒。各地的人们使用不同的偏移量。例如,现代印度使用 +05:30的偏移量,比UTC提前五个半小时。

时区

时区更多。时区是特定区域的人们过去,现在和将来对偏移量的更改的历史记录。

Continent/Region的格式指定 proper time zone name,例如 America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如 ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

java.time

您正在使用可怕的旧类,而这些旧类现在已被JSR 310中定义的现代java.time类所取代。

如果要表示比UTC提前14小时的偏移量,请使用 ZoneOffset

ZoneOffset offset = ZoneOffset.ofHours( 14 ) ;


代表比UTC提前五个半小时的时间。

ZoneOffset offset = ZoneOffset.ofHoursMinutes( 5 , 30 ) ;


更好的是使用时区。该类为 java.time.ZoneId,代替旧版 TimeZone

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;


通过 ZoneId类向 ZoneRules对象询问当前正在使用的偏移量。

ZoneOffset offsetInUseNowInIndia = z.getRules().getOffset( Instant.now() ) ;



  在时区之间进行选择并比较其中两个


让用户选择时区而不是时区偏移会更有意义。但是,如果您坚持要抵消...

使您的列表的类型为 ZoneOffset,而不是字符串。

List< ZoneOffset > offsets ;


让我们获取特定时刻正在使用的所有偏移量。

Instant instant = Instant.now() ;  // Capture the current moment as seen in UTC.


循环所有时区。对于每个,获取规则,并询问偏移量。存储在一个排序的集中 TreeSet中,以消除重复项(许多区域可能在任何特定时刻共享特定的偏移量)。

Set < ZoneOffset > offsets = new TreeSet <>(); // A sorted set of `ZoneOffset`, eliminates duplicates. 

Instant instant = Instant.now(); // Capture the current moment as seen in UTC.
for ( String zoneIdString : ZoneId.getAvailableZoneIds() )
{
ZoneId zoneId = ZoneId.of( zoneIdString );
ZoneOffset offset = zoneId.getRules().getOffset( instant );
offsets.add( offset );
}


转储到控制台。

System.out.println( "offsets = " + offsets );



  偏移量= [+14:00,+ 13:45,+ 13:00,+ 12:00,+ 11:00,+ 10:30,+ 10:00,+ 09:30,+ 09:00,+ 08 :45,+ 08:00,+ 07:00,+ 06:30,+ 06:00,+ 05:45,+ 05:30,+ 05:00,+ 04:30,+ 04:00,+ 03 :30,+03:00,+02:00,+01:00,Z,-01:00,-02:00,-03:00,-03:30,-04:00,-05:00, -06:00,-07:00,-08:00,-09:00,-09:30,-10:00,-11:00,-12:00]


提供 offsets的副本以制作所需的列表。 (我不使用JavaFX。)

您问:


  将其格式化为显示日期的字符串


以我们的代码中的 Instant对象(以UTC表示的当前时刻)为准,并应用 ZoneOffset以获得 OffsetDateTime。同样,这里没有时区,只有偏移量。我建议您改用时区( ZoneIdZoneOffsetZonedDateTimeOffsetDateTime)。但是您要求补偿,所以我们开始吧。

如果您列出的是文本而不是 ZoneOffset对象,请创建一个 ZoneOffset对象。

ZoneOffset offset = ZoneOffset.of( "+05:30" ) ;


将偏移量应用于 Instant对象,生成 OffsetDateTime

OffsetDateTime odt = instant.atOffset( offset ) ;


生成标准 ISO 8601格式的文本。

String output = odt.toString() ;



  odt.toString()= 2020-02-13T02:16:57.883278 + 05:30


那接近您想要的格式。您可以在中间替换 T。并且您忽略了文本的偏移量。我不建议这样做,因为它会使阅读此值的人产生歧义。但是,如果您坚持使用,请使用忽略该偏移量的预定义常量 DateTimeFormatter对象,然后替换 T

String output = 
odt
.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
.replace( "T" , " " )
;



  输出= 2020-02-13 02:16:57.883278


在JavaFX代码中使用数据类型

当我不熟悉JavaFX时,您的弹出菜单小部件似乎支持泛型,并且可以表示智能对象,而不是哑字符串。当使您的 ComboBox类型为 ZoneOffsetComboBox< ZoneOffset >)时,默认情况下,该小部件似乎正在调用 ZoneOffset.toString()以便用户在屏幕上显示文本。该 toString方法在 standard ISO 8601 format中生成文本。

现在,我们不再需要对偏移量列表进行查找。用户的选择本身就是一个 ZoneOffset对象!无需进一步寻找。

示例应用

我今天制作了我的第一个JavaFX应用程序,以演示此代码。

我不知道如何在 Label上添加 Scene,因此我将其留给读者练习。但是您可以在此处看到我们如何获取当前正在使用的所有偏移量的列表。然后,将 ZoneOffset对象的列表分配给我们的弹出菜单小部件 ComboBox< ZoneOffset >。当用户选择一个项目时,该项目本身就是列表中的 ZoneOffset对象。因此,我们不再真正在乎列表本身。这种策略在面向对象的用户界面框架中很常见。

运行应用程序时,每次从列表中选择一个项目时,请查看控制台。

screenshot of demo app running with source code in the background

package work.basil.example;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Set;
import java.util.TreeSet;

/**
* JavaFX App
* Untested code example.
* <p>
* © 2020 Basil Bourque.
* Use by terms of ISC License: https://www.isc.org/licenses/ (basically, do anything but sue me)
*/
public class App extends Application
{
ZoneOffset chosenOffset;

@Override
public void start ( Stage stage )
{
var javaVersion = SystemInfo.javaVersion();
var javafxVersion = SystemInfo.javafxVersion();

Set < ZoneOffset > offsets = new TreeSet <>(); // A sorted set of `ZoneOffset`, eliminates duplicates.

Instant instant = Instant.now(); // Capture the current moment as seen in UTC.
for ( String zoneIdString : ZoneId.getAvailableZoneIds() )
{
ZoneId zoneId = ZoneId.of( zoneIdString );
ZoneOffset offset = zoneId.getRules().getOffset( instant );
offsets.add( offset );
}

System.out.println( "offsets = " + offsets );

ComboBox < ZoneOffset > offsetsMenu = new ComboBox <>();
ObservableList < ZoneOffset > items = FXCollections.observableArrayList( offsets );
offsetsMenu.getItems().addAll( items );
offsetsMenu.getSelectionModel().selectFirst(); // Might be more orthodox than: offsetsMenu.setValue( items.get( 0 ) );
this.chosenOffset = offsetsMenu.getSelectionModel().getSelectedItem(); // Record the default we assign.
offsetsMenu.setOnAction( ( ActionEvent actionEvent ) ->
{
this.chosenOffset = offsetsMenu.getValue();
System.out.println( "DEBUG - User chose ZoneOffset: " + this.chosenOffset );
} );

var scene = new Scene( new StackPane( offsetsMenu ) , 640 , 480 );
stage.setScene( scene );
stage.show();
}

public static void main ( String[] args )
{
launch();
}
}


进一步的信息


这是有关计算一对区域的偏移量差异的问题: Java: Calculating time zone difference
这是一个有关呈现大洲及其区域的问题,用户可以从中选择 ZoneId对象: Android TimeZone.getAvailableIDs() producing strange strings

关于java - 从Lambda表达式中获取时区(java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43506577/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com