如何在androidstudio中为时间选择器设置正确的am/pm时间?

nhhxz33t  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(475)

我正在尝试创建一个基于一些样本城市及其各自时区的时间转换器。我以utc为单位检索当前时间,然后根据每个时区的utc偏移量加上或减去,然后加上或减去12,将时间转换为相应的12小时格式,这样它可以是am或pm。然后,当用户从微调器中选择一个城市时,这些信息就会显示在计时器上。
现在的问题是我得到了正确的时间,但是对于某些时区,am\pm是向后的。例如,我的当地时间是美国东部时间,我想转换成太平洋标准时间。假设现在是晚上7点,我想知道洛杉矶的时间。它显示的不是下午4点,而是凌晨4点。
所以我很难“纠正”时间。我用了一天中的.小时,我认为这应该是夏时制的原因,我试着用小时,但这并不能解决问题,只能把时间推迟一个小时。需要12小时的修正数学来将24小时格式转换为12小时格式,但这并没有像我预期的那样起作用,因为正如我所提到的,虽然它确实设置为正确的小时,但它并不能根据实际时间计算正确的上午/下午。另外,.setis24hourview设置为false。
不管怎样,这里有一个函数来处理这个功能:

public int convertTime(String city)
    {
        //Result of taking in the UTC time and adding/subtracting the offset
        int offset = 0;

        //gets the calender instance of time with GMT standard, then getting hour of day
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        int UTC = c.get(Calendar.HOUR_OF_DAY);

        //set offset according to city
        switch(city)
        {
            case "New York":
                offset = UTC-4;
                break;
            case "London":
                offset = UTC+1;
                break;
            case "Los Angeles":
                offset = UTC-7;
                break;
            case "Dubai":
                offset= UTC+4;
                break;
            case "Paris":
                offset = UTC+2;
                break;
            case "Moscow":
                offset = UTC+3;
                break;
            case "Cairo":
                offset = UTC+2;
                break;
            case "Hong Kong":
                offset = UTC+8;
                break;
            case "Beijing":
                offset = UTC+8;
                break;
            case "New Delhi":
                offset= UTC+5;
                break;
            case "Mexico City":
                offset = UTC-5;
                break;
            case "Brasilia":
                offset = UTC-3;
                break;
        }

        //if the offset is in the AM
        if(offset < 12)
        {
            //set am
            offset = offset+12;
        }
        //if the offset is in the PM
        else if(offset > 12)
        {
            //set pm
            offset = offset-12;
        }
        else
           //its twelve o'clock
            offset = 12;

        return offset;
    }

下面是它在应用程序中的显示方式,用于可视化:时间转换器
编辑:对不起,我也应该加这个。所以偏移量返回的是“转换因子”,我在微调器的onitemselected事件中使用了它。因此,当用户从微调器中选择一个项目时,此函数将读取条目,并根据偏移值设置时间(即小时和分钟,但这也是静态设置的,因为它将始终返回正确的分钟):

@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
 {
    if(convertSpinner.getSelectedItemPosition() == 0)
        {
            //display current/local time
            int hour = c.get(Calendar.HOUR_OF_DAY);
            convertTime.setHour(hour);
            //currentTime.setHour(hour);
        }
        else if(convertSpinner.getSelectedItemPosition()== 1)
            convertTime.setHour(conversionFactory("New York"));
        else if(convertSpinner.getSelectedItemPosition()== 2)
            convertTime.setHour(conversionFactory("London"));
        else if(convertSpinner.getSelectedItemPosition()== 3)
            convertTime.setHour(conversionFactory("Los Angeles"));
        //... same processs for the other cities, shortened for obvious reasons
        else 
            convertTime.setHour(12);
        //set the minute
        int minute = c.get(Calendar.MINUTE);
        convertTime.setMinute(minute);
  }

我的主要观点是:

private TimePicker currentTime, convertTime;
private Spinner convertSpinner;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
    {
        View v= inflater.inflate(R.layout.fragment_time, container, false);
        convertTime = v.findViewById(R.id.convert_clock);
        convertSpinner = v.findViewById(R.id.convert_spinner);

        convertTime.setIs24HourView(false);
        convertTime.setClickable(false);

        //for convert spinner
        ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(getActivity(),R.array.time_cities, android.R.layout.simple_spinner_item);
        adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        convertSpinner.setAdapter(adapter2);
        convertSpinner.setOnItemSelectedListener(this);

        return v;
}
pgpifvop

pgpifvop1#

java.time文件

考虑在您的时间工作中使用java.time,即现代的java日期和时间api。尤其是像你这样琐碎的事情。
要获取洛杉矶的当前时间:

LocalTime timeInLa = LocalTime.now(ZoneId.of("America/Los_Angeles"));
    System.out.println("Current time in LA: " + timeInLa);

刚才运行时的输出:
洛杉矶当前时间:11:10:18.975
例如,对于其他城市,请提供相应的时区id Europe/London 或者 Asia/Dubai . 巴西利亚的身份证是 America/Sao_Paulo . 我建议您构建一个从城市名称到时区id的Map,这样您就可以在Map查找过程中获得id,而不需要很长的时间 switch 声明。
一旦我们有了 LocalTime 对象,我们可以去掉一天中的时间。

int hourOfDayInLa = timeInLa.getHour();
    System.out.println("Hour of day in LA: " + hourOfDayInLa);

洛杉矶每天11点
你是否需要对这个值做任何调整,让你的时间选择器显示正确的时间-我当然不希望这样,但这不是我知道也不能告诉你的。
我可以告诉你的是,我们也可以从计算机上得到上午或下午的时钟时间,上午0点或下午1点 LocalTime 对象:

int clockHourOfAmOrPm = timeInLa.get(ChronoField.CLOCK_HOUR_OF_AMPM);
    int amOrPmIndexInLa = timeInLa.get(ChronoField.AMPM_OF_DAY);
    String amPm = amOrPmIndexInLa == 0 ? "AM" : "PM";
    System.out.format("Clock hour %d (1 through 12) %s (code %d)%n",
            clockHourOfAmOrPm, amPm, amOrPmIndexInLa);

上午11点(1到12点)(代码0)
(如果最终目标是一根弦 AM 或者 PM ,我们应该为此使用格式化程序:我在想,如果您想根据am或pm进行进一步处理,那么 int 值为0或1更为实际。)

问:java.time不需要androidapi级别26吗?

java.time在较旧和较新的android设备上都能很好地工作。它至少需要Java6。
在Java8和更高版本以及更新的android设备上(api级别26),现代api是内置的。
在非android的java6和java7中获得了三个十的backport,即现代类的backport(三个十用于jsr310;请参见底部的链接)。
在旧的android上,要么使用desugaring,要么使用android版本的threeten backport。它叫3TENABP。在后一种情况下,请确保从导入日期和时间类 org.threeten.bp 有分装的。

链接

oracle教程:date time解释如何使用java.time。
java规范请求(jsr)310,其中 java.time 第一次被描述。
三十后港工程 java.time 到Java6和Java7(jsr-310为310)。
通过desugaring提供Java8+API
threetenabp,android版threeten backport
问:如何在android项目中使用threetenabp,有非常透彻的解释。

ghhaqwfi

ghhaqwfi2#

你不需要重新发明轮子。

您应该使用ootb(开箱即用)日期时间api,而不是使用那么多容易出错的复杂逻辑。无论是现代的还是传统的api,都有更简单的方法来处理复杂的自定义逻辑。
但是,遗留的日期时间api,即 java.util 以及它们的格式化api, SimpleDateFormat 过时且容易出错。建议完全停止使用它们,并切换到现代日期时间api。出于任何原因,如果您必须坚持使用Java6或Java7,您可以使用threeten backport,它将大部分java.time功能向后移植到Java6和Java7。如果您正在为一个android项目工作,并且您的android api级别仍然不符合java-8,请检查通过desugaring提供的java8+api以及如何在android项目中使用threetenabp。

定义时区不仅需要城市,还需要整个大陆。

表示时区字符串的标准格式是大陆/城市。
使用现代api:

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String... args) {
        // Test
        System.out.println(getOffset("Europe/London"));
        System.out.println(getOffset("Africa/Johannesburg"));
        System.out.println(getOffset("America/Chicago"));
        System.out.println(getOffset("Asia/Calcutta"));
    }

    public static ZoneOffset getOffset(String zoneId) {
        return ZonedDateTime.now(ZoneId.of(zoneId)).getOffset();
    }
}

输出:

Z
+02:00
-06:00
+05:30

请注意 Z 代表 Zulu 指定的时间 UTC (其时区偏移为 +00:00 小时)。
使用旧api:

import java.util.TimeZone;

public class Main {
    public static void main(String... args) {
        // Test
        System.out.println(getOffset("Europe/London"));
        System.out.println(getOffset("Africa/Johannesburg"));
        System.out.println(getOffset("America/Chicago"));
        System.out.println(getOffset("Asia/Calcutta"));
    }

    public static String getOffset(String zoneId) {
        int offset = TimeZone.getTimeZone(zoneId).getRawOffset();// milliseconds to be added to UTC
        int seconds = offset / 1000;
        int hours = seconds / 3600;
        int minutes = (seconds % 3600) / 60;
        return "GMT" + (offset >= 0 ? "+" : "-") + String.format("%02d", Math.abs(hours)) + ":"
                + String.format("%02d", minutes);
    }
}

输出:

GMT+00:00
GMT+02:00
GMT-06:00
GMT+05:30

如何将日期时间从一个时区转换为另一个时区:

使用现代日期时间api,您可以 ZonedDateTime#withZoneSameInstant 以及 OffsetDateTime#withOffsetSameInstant 为了得到 ZonedDateTime 以及 OffsetDateTime 分别在指定的时区。
ZoneDateTime演示

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String... args) {
        // Test
        ZonedDateTime zdt = ZonedDateTime.now(ZoneId.systemDefault());
        System.out.println(zdt);
        System.out.println(getZonedDateTimeWithZoneId(zdt, "Europe/London"));
        System.out.println(getZonedDateTimeWithZoneId(zdt, "Africa/Johannesburg"));
        System.out.println(getZonedDateTimeWithZoneId(zdt, "America/Chicago"));
        System.out.println(getZonedDateTimeWithZoneId(zdt, "Asia/Calcutta"));
    }

    public static ZonedDateTime getZonedDateTimeWithZoneId(ZonedDateTime zdt, String zoneId) {
        return zdt.withZoneSameInstant(ZoneId.of(zoneId));
    }
}

输出:

2020-12-28T20:03:54.093476Z[Europe/London]
2020-12-28T20:03:54.093476Z[Europe/London]
2020-12-28T22:03:54.093476+02:00[Africa/Johannesburg]
2020-12-28T14:03:54.093476-06:00[America/Chicago]
2020-12-29T01:33:54.093476+05:30[Asia/Calcutta]

offsetdatetime演示

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String... args) {
        // Test
        OffsetDateTime odt = OffsetDateTime.now(ZoneId.systemDefault());
        System.out.println(odt);
        System.out.println(getOffsetDateTimeWithZoneId(odt, "Europe/London"));
        System.out.println(getOffsetDateTimeWithZoneId(odt, "Africa/Johannesburg"));
        System.out.println(getOffsetDateTimeWithZoneId(odt, "America/Chicago"));
        System.out.println(getOffsetDateTimeWithZoneId(odt, "Asia/Calcutta"));
    }

    public static OffsetDateTime getOffsetDateTimeWithZoneId(OffsetDateTime odt, String zoneId) {
        return odt.withOffsetSameInstant(getOffset(zoneId));
    }

    public static ZoneOffset getOffset(String zoneId) {
        return ZonedDateTime.now(ZoneId.of(zoneId)).getOffset();
    }
}

输出:

2020-12-28T20:08:25.026349Z
2020-12-28T20:08:25.026349Z
2020-12-28T22:08:25.026349+02:00
2020-12-28T14:08:25.026349-06:00
2020-12-29T01:38:25.026349+05:30

使用传统api:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String... args) throws ParseException {
        // Test
        Date date = Calendar.getInstance().getTime();
        System.out.println(date);
        System.out.println(getFormattedDateTimeWithZoneId(date, "Europe/London"));
        System.out.println(getFormattedTimeWithZoneId(date, "Europe/London"));
        System.out.println(getFormattedDateTimeWithZoneId(date, "Africa/Johannesburg"));
        System.out.println(getFormattedTimeWithZoneId(date, "Africa/Johannesburg"));
        System.out.println(getFormattedDateTimeWithZoneId(date, "America/Chicago"));
        System.out.println(getFormattedTimeWithZoneId(date, "America/Chicago"));
        System.out.println(getFormattedDateTimeWithZoneId(date, "Asia/Calcutta"));
        System.out.println(getFormattedTimeWithZoneId(date, "Asia/Calcutta"));
    }

    public static String getFormattedDateTimeWithZoneId(Date date, String zoneId) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a zzz", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone(getOffset(zoneId)));
        return sdf.format(date);
    }

    public static String getFormattedTimeWithZoneId(Date date, String zoneId) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss a", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone(getOffset(zoneId)));
        return sdf.format(date);
    }

    public static String getOffset(String zoneId) {
        int offset = TimeZone.getTimeZone(zoneId).getRawOffset();// milliseconds to be added to UTC
        int seconds = offset / 1000;
        int hours = seconds / 3600;
        int minutes = (seconds % 3600) / 60;
        return "GMT" + (offset >= 0 ? "+" : "-") + String.format("%02d", Math.abs(hours)) + ":"
                + String.format("%02d", minutes);
    }
}

输出:

Mon Dec 28 20:47:25 GMT 2020
2020-12-28 08:47:25 PM GMT+00:00
08:47:25 PM
2020-12-28 10:47:25 PM GMT+02:00
10:47:25 PM
2020-12-28 02:47:25 PM GMT-06:00
02:47:25 PM
2020-12-29 02:17:25 AM GMT+05:30
02:17:25 AM

从trail:date-time了解现代日期时间api。

相关问题