如何在 Vaadin Flow 中检索客户端(浏览器)时区?
How to retrieve the client (browser) timezone in Vaadin Flow?
我需要确定浏览器时区。我尝试遵循 this post 但不起作用 (Vaadin 20)。这是我的代码:
ZoneId myZoneId;
...
UI.getCurrent().getPage().retrieveExtendedClientDetails(extendedClientDetails -> {
myZoneId = ZoneId.of(extendedClientDetails.getTimeZoneId());
});
// here myZoneId has value null.
所以我尝试自己做,最初只是简单地展示它。
UI.getCurrent().getPage()
.executeJs("return Intl.DateTimeFormat().resolvedOptions().timeZone;")
.then(value -> Notification.show(value.asString()));
它有效,我读到“Europe/Rome”,但它的值似乎无法映射到 Java 中的 ZoneId。
我可以进一步探索 Javascript zone 对象,但我也无法找到我的代码实际去哪里用 chrome 调试器调试它(Vaadin 文档中没有提及代码在哪里)。
我可以处理返回值并尝试解释它,但我想避免重新发明轮子。
有人有可用的代码吗?
Europe/Rome 适用于 Java.
您只需致电:
ZoneId.of("Europe/Rome");
retrieveExtendedClientDetails
是异步调用,因此结果在 inside 回调中可用,而不是在 after 触发回调时可用(在你评论的地方)。
此外,UI.getCurrent()
可以 return null
如果调用得太快,f.e。在构造函数中。
retrieveExtendedClientDetails
第一次使客户端往返 运行 (docs).
If already obtained, the callback is called directly. Otherwise, a client-side roundtrip will be carried out.
这意味着您可以在初始化 UI 时尝试 运行 它,稍后您应该在触发后立即准备好它。
@SpringComponent
public class MyVaadinServiceInitListener implements VaadinServiceInitListener {
@Override
public void serviceInit(ServiceInitEvent event) {
event.getSource().addUIInitListener(uiEvent -> {
var ui = event.getUI();
ui.getPage().retrieveExtendedClientDetails(detail -> {});
});
}
}
另一个解决方案是读取回调中的区域。
试试这个
//Read the timezone and store in into the session class
if(UI.getCurrent() != null) {
UI.getCurrent().getPage().retrieveExtendedClientDetails(details -> {
// Set the time zone
TimeZone uiTimeZone = TimeZone.getTimeZone(details.getTimeZoneId());
});
};
谢谢大家!
最后,主要问题不是从客户端检索时区,而是将其与 ZoneId.getAvailableZoneIds()
返回的可用时区列表进行匹配。事实上,CEST(中欧)和任何其他国家都有多个时区。只有5个时区的巴西我算了7个!
老实说,我对时区一无所知(如果我们可以只使用 GMT 并相应地调整我们的日程安排,世界会变得非常简单)。解决方案是使用名称消化时区列表。我不知道这是对还是错,但它很简单而且有效,尽管如果我选择 CEST,我不知道它会是罗马、柏林还是其他任何地方。重要吗?
如果有一天有人需要
,这里是完整的代码
package net.cbsolution.scc.vaadin.comps;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.ItemLabelGenerator;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.data.renderer.TemplateRenderer;
import java.time.ZoneId;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;
public class TimeZoneSelector extends ComboBox<ZoneId> {
private Locale locale = UI.getCurrent().getLocale();
public TimeZoneSelector() {
// Digest the timezone list
final Map<String, ZoneId> cleanMap = new HashMap<>();
ZoneId.getAvailableZoneIds().stream().map(z -> ZoneId.of(z)).forEach(z -> cleanMap.put(print(z), z));
cleanMap.values().stream().collect(Collectors.toList());
setWidth("20em");
setDataProvider(new ListDataProvider<>(cleanMap.values().stream().collect(Collectors.toList())));
setRenderer(TemplateRenderer.<ZoneId>of("<span>[[item.print]]</span>")
.withProperty("print", tz -> print(tz))
);
setItemLabelGenerator((ItemLabelGenerator<ZoneId>) item -> print(item));
}
protected String print(ZoneId zoneId) {
return zoneId.getDisplayName(TextStyle.FULL, UI.getCurrent().getLocale());
}
@Override
protected void onAttach(AttachEvent attachEvent) {
UI.getCurrent().getPage().retrieveExtendedClientDetails(details -> {
TimeZone uiTimeZone = TimeZone.getTimeZone(details.getTimeZoneId());
setValue(ZoneId.of(uiTimeZone.getID()));
});
}
}
我需要确定浏览器时区。我尝试遵循 this post 但不起作用 (Vaadin 20)。这是我的代码:
ZoneId myZoneId;
...
UI.getCurrent().getPage().retrieveExtendedClientDetails(extendedClientDetails -> {
myZoneId = ZoneId.of(extendedClientDetails.getTimeZoneId());
});
// here myZoneId has value null.
所以我尝试自己做,最初只是简单地展示它。
UI.getCurrent().getPage()
.executeJs("return Intl.DateTimeFormat().resolvedOptions().timeZone;")
.then(value -> Notification.show(value.asString()));
它有效,我读到“Europe/Rome”,但它的值似乎无法映射到 Java 中的 ZoneId。
我可以进一步探索 Javascript zone 对象,但我也无法找到我的代码实际去哪里用 chrome 调试器调试它(Vaadin 文档中没有提及代码在哪里)。
我可以处理返回值并尝试解释它,但我想避免重新发明轮子。
有人有可用的代码吗?
Europe/Rome 适用于 Java.
您只需致电:
ZoneId.of("Europe/Rome");
retrieveExtendedClientDetails
是异步调用,因此结果在 inside 回调中可用,而不是在 after 触发回调时可用(在你评论的地方)。
此外,UI.getCurrent()
可以 return null
如果调用得太快,f.e。在构造函数中。
retrieveExtendedClientDetails
第一次使客户端往返 运行 (docs).
If already obtained, the callback is called directly. Otherwise, a client-side roundtrip will be carried out.
这意味着您可以在初始化 UI 时尝试 运行 它,稍后您应该在触发后立即准备好它。
@SpringComponent
public class MyVaadinServiceInitListener implements VaadinServiceInitListener {
@Override
public void serviceInit(ServiceInitEvent event) {
event.getSource().addUIInitListener(uiEvent -> {
var ui = event.getUI();
ui.getPage().retrieveExtendedClientDetails(detail -> {});
});
}
}
另一个解决方案是读取回调中的区域。
试试这个
//Read the timezone and store in into the session class
if(UI.getCurrent() != null) {
UI.getCurrent().getPage().retrieveExtendedClientDetails(details -> {
// Set the time zone
TimeZone uiTimeZone = TimeZone.getTimeZone(details.getTimeZoneId());
});
};
谢谢大家!
最后,主要问题不是从客户端检索时区,而是将其与 ZoneId.getAvailableZoneIds()
返回的可用时区列表进行匹配。事实上,CEST(中欧)和任何其他国家都有多个时区。只有5个时区的巴西我算了7个!
老实说,我对时区一无所知(如果我们可以只使用 GMT 并相应地调整我们的日程安排,世界会变得非常简单)。解决方案是使用名称消化时区列表。我不知道这是对还是错,但它很简单而且有效,尽管如果我选择 CEST,我不知道它会是罗马、柏林还是其他任何地方。重要吗?
如果有一天有人需要
,这里是完整的代码package net.cbsolution.scc.vaadin.comps;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.ItemLabelGenerator;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.data.renderer.TemplateRenderer;
import java.time.ZoneId;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;
public class TimeZoneSelector extends ComboBox<ZoneId> {
private Locale locale = UI.getCurrent().getLocale();
public TimeZoneSelector() {
// Digest the timezone list
final Map<String, ZoneId> cleanMap = new HashMap<>();
ZoneId.getAvailableZoneIds().stream().map(z -> ZoneId.of(z)).forEach(z -> cleanMap.put(print(z), z));
cleanMap.values().stream().collect(Collectors.toList());
setWidth("20em");
setDataProvider(new ListDataProvider<>(cleanMap.values().stream().collect(Collectors.toList())));
setRenderer(TemplateRenderer.<ZoneId>of("<span>[[item.print]]</span>")
.withProperty("print", tz -> print(tz))
);
setItemLabelGenerator((ItemLabelGenerator<ZoneId>) item -> print(item));
}
protected String print(ZoneId zoneId) {
return zoneId.getDisplayName(TextStyle.FULL, UI.getCurrent().getLocale());
}
@Override
protected void onAttach(AttachEvent attachEvent) {
UI.getCurrent().getPage().retrieveExtendedClientDetails(details -> {
TimeZone uiTimeZone = TimeZone.getTimeZone(details.getTimeZoneId());
setValue(ZoneId.of(uiTimeZone.getID()));
});
}
}