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 的这些功能都能提供有力的支持。
超级会员免费看
598

被折叠的 条评论
为什么被折叠?



