90、Java 中的货币与日期时间处理

Java 中的货币与日期时间处理

在 Java 编程中,货币和日期时间的处理是非常常见且重要的任务。下面将详细介绍 Java 中货币和日期时间的相关处理方法。

1. 货币处理

货币编码对地区非常敏感, java.util.Currency 类可以帮助我们正确格式化货币值。我们可以通过其静态的 getInstance 方法获取 Currency 对象,该方法有两种重载形式:一种接受 Locale 对象,另一种接受字符串类型的货币代码(代码遵循 ISO 4217 标准)。

Currency 类本身并不直接将货币值映射为本地化字符串,而是提供了一些必要的信息,具体如下:
| 方法 | 描述 |
| — | — |
| public String getSymbol() | 返回该货币在默认地区的符号 |
| public String getSymbol(Locale locale) | 返回该货币在指定地区的符号。如果没有特定地区的符号,则返回 ISO 4217 货币代码 |
| public int getDefaultFractionDigits() | 返回该货币默认的小数位数 |
| public String getCurrencyCode() | 返回该货币的 ISO 4217 货币代码 |

以下是一个示例,要求选择六个不同的地区和六种不同的货币,并打印出每个货币在每个地区的货币符号:

Exercise 24.2: Select six different locales and six different currencies, and print a table showing the 
currency symbol for each currency in each locale.

通过这些方法,我们可以灵活地处理不同地区的货币符号和小数位数,确保货币信息在不同地区的正确显示。

2. 时间、日期和日历处理
2.1 时间表示

时间在 Java 中以长整型表示,单位为毫秒,从 1970 年 1 月 1 日午夜格林威治标准时间(GMT)开始计算,这个起始点被称为纪元。 System.currentTimeMillis 方法可以返回当前时间。这个值是有符号的,负数表示纪元开始之前的时间。该值可以表示到公元 292,280,995 年,足以满足大多数需求。

我们可以使用 java.util.Date 类来存储时间并执行一些简单的时间相关操作。创建 Date 对象时,可以指定一个长整型的时间值。如果使用无参构造函数, Date 对象将记录其创建的时间。以下是一个简单的程序,用于打印当前时间:

import java.util.Date;
class Date2 {
    public static void main(String[] args) {
        Date now = new Date();
        System.out.println(now);
    }
}

该程序的输出示例如下:

Sun Mar 20 08:48:38 GMT+10:00 2005

需要注意的是,这不是本地化输出,无论默认地区是什么,日期都将以这种格式显示,并根据当前时区进行调整。我们可以使用 before after 方法比较两个日期,也可以比较通过 getTime 方法获取的长整型值。 setTime 方法可以将时间更改为不同的长整型值。不过, Date 类不支持本地化,已被更复杂且支持地区的 Calendar DateFormat 类所取代。

2.2 日历处理

日历用于标记时间的流逝。世界上大多数地区使用的是公历(Gregorian calendar),它是以教皇格列高利十三世的名字命名的。日历抽象包括以下几个部分:
- 抽象的 Calendar 类:表示各种标记时间的方式
- 抽象的 TimeZone 类:表示时区偏移和其他调整,如夏令时
- 抽象的 java.text.DateFormat 类:定义了如何格式化和解析日期和时间字符串

由于公历使用广泛,我们有以下具体实现:
- GregorianCalendar
- 用于 GregorianCalendar SimpleTimeZone
- 用于格式化和解析公历日期和时间的 java.text.SimpleDateFormat

以下是一个创建 GregorianCalendar 对象并打印其值的示例:

import java.util.Calendar;
import java.util.GregorianCalendar;

class CalendarExample {
    public static void main(String[] args) {
        Calendar cal = new GregorianCalendar(1972, Calendar.OCTOBER, 26);
        System.out.println(cal.getTime());
    }
}

该程序的输出示例如下:

Thu Oct 26 00:00:00 GMT+10:00 1972

我们还可以直接使用 getTimeInMillis setTimeInMillis 方法处理毫秒级的时间值,这与使用 Date 对象是等效的。

Calendar 类提供了许多常量,如 Calendar.AM Calendar.PM 用于 12 小时制的日历。每个 Calendar 对象表示该日历上的一个特定时刻,其构造函数只能创建当前时间的对象,可以在默认地区和时区或指定的地区和时区中创建。

我们可以通过 Calendar.getInstance 静态方法获取指定地区的日历对象。无参调用时, getInstance 返回默认地区和时区的最佳可用日历类型(目前仅为 GregorianCalendar ),并设置为当前时间。其他重载方法允许我们指定地区、时区或两者。 getAvailableLocales 静态方法返回系统上安装了日历的 Locale 对象数组。

有了日历对象,我们就可以对日期进行操作。以下是一个打印给定日历对象下一周日期的示例:

import java.io.PrintStream;
import java.util.Calendar;

public class CalendarManipulation {
    public static void oneWeek(PrintStream out, Calendar cal) {
        Calendar cur = (Calendar) cal.clone(); // modifiable copy
        int dow = cal.get(Calendar.DAY_OF_WEEK);
        do {
            out.println(cur.getTime());
            cur.add(Calendar.DAY_OF_WEEK, 1);
        } while (cur.get(Calendar.DAY_OF_WEEK) != dow);
    }
}

Calendar 类定义了许多日历字段,如 DAY_OF_WEEK 等,这些字段是常量,用于在操作时间部分的方法中指定日历字段。相关方法如下:
| 方法 | 描述 |
| — | — |
| get | 返回字段的值 |
| set | 将字段的值设置为指定的整数 |
| clear | 将字段的值重置为“未指定” |
| isSet | 如果字段当前已设置值,则返回 true |
| add | 向指定字段添加一个整数值 |
| roll | 如果第二个布尔参数为 true ,则将字段值递增到下一个值;否则递减 |
| getMinimum | 获取字段的最小有效值 |
| getMaximum | 获取字段的最大有效值 |
| getGreatestMinimum | 获取字段的最高最小值;如果值可变,可能与 getMinimum 不同 |
| getLeastMaximum | 获取字段的最小最大值;如果值可变,可能与 getMaximum 不同 |

以下是一个计算特定日期是星期几的示例:

import java.util.Calendar;
import java.util.GregorianCalendar;

public class DayOfWeekCalculator {
    public static int dotw(int year, int month, int date) {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DATE, date);
        return cal.get(Calendar.DAY_OF_WEEK);
    }
}

此外, Calendar 类还提供了一些其他的方法,如 setLenient 方法可以设置日历是否宽松解析, getFirstDayOfWeek 方法可以获取一周的第一天, getMinimalDaysInFirstWeek 方法可以获取一年中第一周所需的最少天数等。我们还可以使用 compareTo before after 方法比较两个 Calendar 对象。

通过以上内容,我们可以看到 Java 提供了丰富的类和方法来处理货币和日期时间,能够满足不同场景下的需求。无论是处理不同地区的货币显示,还是进行复杂的日期时间计算和比较,都可以借助这些类和方法轻松实现。

下面是一个简单的流程图,展示了获取日历对象并操作日期的基本流程:

graph TD;
    A[开始] --> B[获取日历对象];
    B --> C[操作日历字段];
    C --> D[输出日期信息];
    D --> E[结束];

通过这个流程图,我们可以更清晰地理解使用 Calendar 类进行日期操作的基本步骤。在实际应用中,我们可以根据具体需求对这个流程进行扩展和调整。

Java 中的货币与日期时间处理(续)

2.3 时区处理

TimeZone 是一个抽象类,它不仅封装了与 GMT 的偏移量,还处理其他偏移问题,如夏令时。和其他支持地区的类一样,我们可以通过调用静态方法 getDefault 来获取默认的 TimeZone 对象。也可以通过 setDefault 方法传入一个新的 TimeZone 对象来更改默认时区,传入 null 则可以重置为原始的默认时区。需要注意的是,不同的日历类型对时区的理解不同,所以要确保默认日历和时区是兼容的。

每个时区都有一个字符串标识符,采用由主要和次要区域名称组成的长格式,用 / 分隔,例如 America/New_York Australia/Brisbane Africa/Timbuktu 等。许多时区还有短标识符,通常是三个字母的缩写,部分短标识符是为了向后兼容而被 TimeZone 识别。不过,建议始终使用长格式,因为短格式可能无法明确表示所属国家。此外, TimeZone 还识别以与 GMT 的时间差表示的通用标识符,如 GMT+10:00 GMT - 4:00 。我们可以通过静态方法 getAvailableIDs 获取系统上所有可用的标识符数组,如果只需要特定偏移量的标识符,可以传入偏移量调用该方法。

以下是获取和设置时区标识符的相关操作:

import java.util.TimeZone;

public class TimeZoneExample {
    public static void main(String[] args) {
        TimeZone timeZone = TimeZone.getDefault();
        String id = timeZone.getID();
        System.out.println("当前时区标识符: " + id);

        // 设置新的时区标识符
        timeZone.setID("America/New_York");
        System.out.println("设置后的时区标识符: " + timeZone.getID());
    }
}

我们可以使用 getDisplayName 方法将时区转换为可显示的形式,该方法允许指定使用默认地区还是指定地区,以及使用短格式还是长格式。返回的字符串由 DateFormat 对象控制,该对象维护着如何格式化不同时区的信息表。

每个时区都有一个相对于 GMT 的原始偏移量,可正可负。我们可以使用 getRawOffset setRawOffset 方法获取或设置这个原始偏移量,但通常很少需要这样做。

夏令时会在原始偏移量的基础上增加一个季节性的时间偏移。这个偏移值可以通过 getDSTSavings 方法获取,默认实现返回 3600000(即一小时的毫秒数)。我们可以通过调用 useDaylightTime 方法来判断一个时区在一年中是否使用夏令时,该方法返回一个布尔值。 inDaylightTime 方法用于判断传入的 Date 参数是否处于该时区的夏令时范围内,如果是则返回 true

以下是一些时区偏移和夏令时相关方法的使用示例:

import java.util.Date;
import java.util.TimeZone;

public class TimeZoneOffsetExample {
    public static void main(String[] args) {
        TimeZone timeZone = TimeZone.getDefault();

        // 获取原始偏移量
        int rawOffset = timeZone.getRawOffset();
        System.out.println("原始偏移量(毫秒): " + rawOffset);

        // 判断是否使用夏令时
        boolean usesDST = timeZone.useDaylightTime();
        System.out.println("该时区是否使用夏令时: " + usesDST);

        // 判断某个日期是否处于夏令时
        Date date = new Date();
        boolean inDST = timeZone.inDaylightTime(date);
        System.out.println("当前日期是否处于夏令时: " + inDST);
    }
}

我们可以通过指定日期的毫秒数或使用日历字段指定年、月等来获取某个时区在给定日期的精确偏移量。相关方法如下:
| 方法 | 描述 |
| — | — |
| public int getOffset(long date) | 返回该时区在给定时间相对于 GMT 的偏移量,会考虑夏令时偏移 |
| public abstract int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) | 返回该时区在给定时间相对于 GMT 的偏移量,会考虑夏令时偏移,所有参数都相对于该时区实现所设计的日历进行解释, era 参数表示特定日历的纪元,如公历中的 B.C. 和 A.D. |

2.4 公历和简单时区类

GregorianCalendar 类是 Calendar 的具体子类,它反映了协调世界时(UTC),不过由于底层系统的时间机制,可能无法完全精确表示。日期的各个部分按照 UTC 标准单位和范围指定,其范围如下:
| 字段 | 范围 |
| — | — |
| YEAR | 1 - 292278994 |
| MONTH | 0 - 11 |
| DATE | 1 - 31 |
| HOUR_OF_DAY | 0 - 23 |
| MINUTE | 0 - 59 |
| SECOND | 0 - 59 |
| MILLISECOND | 0 - 999 |

GregorianCalendar 类支持多种构造函数:
- public GregorianCalendar() :创建一个表示默认时区和默认地区当前时间的 GregorianCalendar 对象。
- public GregorianCalendar(int year, int month, int date, int hrs, int min, int sec) :创建一个表示默认时区和默认地区给定日期的 GregorianCalendar 对象。
- public GregorianCalendar(int year, int month, int date, int hrs, int min) :等同于 GregorianCalendar(year, month, date, hrs, min, 0) ,即指定分钟的开始。
- public GregorianCalendar(int year, int month, int date) :等同于 GregorianCalendar(year, month, date, 0, 0, 0) ,即给定日期的午夜(被视为一天的开始)。
- public GregorianCalendar(Locale locale) :创建一个表示默认时区和给定地区当前时间的 GregorianCalendar 对象。
- public GregorianCalendar(TimeZone timeZone) :创建一个表示给定 timeZone 和默认地区当前时间的 GregorianCalendar 对象。
- public GregorianCalendar(TimeZone zone, Locale locale) :创建一个表示给定 timeZone 和给定地区当前时间的 GregorianCalendar 对象。

除了从 Calendar 类继承的方法外, GregorianCalendar 类还提供了 isLeapYear 方法,用于判断传入的年份是否为该日历中的闰年。

在许多地方,公历之前使用的是儒略历。在 GregorianCalendar 对象中,默认的历法变更时间是 1582 年 10 月 15 日午夜当地时间。不过不同国家的变更时间可能不同。我们可以使用 getGregorianChange 方法获取当前日历使用的变更时间,使用 setGregorianChange 方法传入一个 Date 对象来设置日历的变更时间。

SimpleTimeZone 类是 TimeZone 的具体子类,它用于表示公历的时区值。它不处理历史复杂性,而是将当前的做法应用到所有时间。例如,对于使用夏令时之前的历史日期,我们可能需要选择一个忽略夏令时的时区的日历;对于未来日期, SimpleTimeZone 可能是一个不错的选择。

下面是一个使用 GregorianCalendar SimpleTimeZone 的示例:

import java.util.GregorianCalendar;
import java.util.SimpleTimeZone;
import java.util.TimeZone;

public class GregorianAndSimpleTimeZoneExample {
    public static void main(String[] args) {
        // 创建一个 SimpleTimeZone 对象
        TimeZone timeZone = new SimpleTimeZone(36000000, "Asia/Shanghai");
        // 创建一个 GregorianCalendar 对象
        GregorianCalendar cal = new GregorianCalendar(timeZone);
        System.out.println(cal.getTime());
    }
}

以下是一个流程图,展示了处理日期时间时涉及的主要类和操作流程:

graph LR;
    A[Date] --> B[Calendar];
    B --> C[GregorianCalendar];
    B --> D[TimeZone];
    D --> E[SimpleTimeZone];
    B --> F[DateFormat];
    F --> G[SimpleDateFormat];
    C --> H[日期操作];
    D --> I[时区调整];
    F --> J[日期格式化与解析];

通过这个流程图,我们可以更清晰地看到 Date Calendar TimeZone DateFormat 等类之间的关系以及它们在处理日期时间时的作用。

综上所述,Java 在货币和日期时间处理方面提供了丰富的功能和灵活的机制。通过 Currency 类可以处理不同地区的货币表示,利用 Calendar TimeZone 等类可以进行复杂的日期时间计算、时区调整和格式化。开发者可以根据具体需求选择合适的类和方法,实现高效、准确的货币和日期时间处理。无论是开发财务系统、日程管理应用还是其他需要处理时间和货币的程序,Java 的这些功能都能提供有力的支持。

【EI复现】基于深度强化学习的微能源网能量管理优化策略研究(Python代码实现)内容概要:本文围绕“基于深度强化学习的微能源网能量管理优化策略”展开研究,重点利用深度Q网络(DQN)等深度强化学习算法对微能源网中的能量调度进行建模优化,旨在应对可再生能源出力波动、负荷变化及运行成本等问题。文中结合Python代码实现,构建了包含光伏、储能、负荷等元素的微能源网模型,通过强化学习智能体动态决策能量分配策略,实现经济性、稳定性和能效的多重优化目标,并可能其他优化算法进行对比分析以验证有效性。研究属于电力系统人工智能交叉领域,具有较强的工程应用背景和学术参考价值。; 适合人群:具备一定Python编程基础和机器学习基础知识,从事电力系统、能源互联网、智能优化等相关方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①学习如何将深度强化学习应用于微能源网的能量管理;②掌握DQN等算法在实际能源系统调度中的建模实现方法;③为相关课题研究或项目开发提供代码参考和技术思路。; 阅读建议:建议读者结合提供的Python代码进行实践操作,理解环境建模、状态空间、动作空间及奖励函数的设计逻辑,同时可扩展学习其他强化学习算法在能源系统中的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值